java基础补充

1、 ++和--参加混合运算

++在前 先自增 拿自增后的值参加本次运算
++在后 先进行本次运算 再自增
//++ --的混合运算
int a,b=2;
a=(++b)+b/(--b)+3*(b++)+b+b--;
//b=2 3  2 3 2
// 3+3/2  +3*2+3+3=3+1+6+3+3=
System.out.println(a+"::"+b);//16+2
//注意
int a=1;
a=a++;//此时a的值仍未1
a=++a;//此时a的值为2

2 、不定参数

public static void main(String[] args) {
		//1.8的新特性:不定参数::基本等价于数组
		test2(1,2,3,4);
		test2(1);
		test2();
		test2(new int[]{1,2,3,4});
	}
	//int[] arr=new int[0];
	static void test1(int[] arr){//方法参数:可以是n个int n>=0
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i]+(i==arr.length-1?"\n":","));
		}
	}
	static void test2(int...n){//方法参数:可以是n个int n>=0
		System.out.println(n);//[I@15db9742
	}
//	static void test2(int[] n){//方法参数:可以是n个int n>=0
//		System.out.println(n);//[I@15db9742
//	}
	static void test3(long l,int...n){//方法参数:可以是n个int n>=0
		System.out.println(n);//[I@15db9742
	}
//	static void test4(int...n,float f){//不定参数必须是最后一个参数
//		System.out.println(n);//[I@15db9742
//	}
//输出的话,把n当成数组遍历就行啦

3、代码块

//类的组成
class Test{
	//1 实例变量
	int a;
	//2 类变量
	static int b;//共享数据
	//3 实例方法
	void show(){}
	//4 类方法
	static void hehe(){}//如果一个方法没有涉及实例成员 尽量写成类方法
	
	//5 构造方法
	Test(){}
	//6内部类
	class Inner{}
	//7构造代码块:每创建对象时  都执行一次:
	// 构造代码块 一般用于给对象的实例变量初始化
	{
		a=1;
		System.out.println("构造代码块---------");
	}
	
	//8 静态代码块:只有在类加载时 执行一次
	//静态代码块一般用于给类变量初始化
	static{
		b=1;
		System.out.println("静态代码块---");
	}
}
//即使new很多次对象,类加载的代码块也只会执行一次
//但是调用静态方法,静态方法可以执行多次,静态方法可以不用实例化之间类名.方法调用就行

4、 字符串缓冲区(重点)

  • 方法
    * String,StringBuffer,StringBuilder
	 * String:字符串常量 字符序列不能更改
	 * StringBuffered和StringBuilder:字符串缓冲区 字符序列可以更改
	 * 相同之处:都可以描述字符串
	 * 不同之处: String:字符串常量 字符串对象一旦创建 字符序列不能更改
	 *         StringBuffer和StringBuilder:都是字符串缓冲区 字符长度和字符序列都可以更改
	 *         StringBuffer和StringBuilder都是字符串缓冲区 API兼容(方法完全相同)
	 *         版本不同:StringBuilder 1.5   StringBuffer 1.0
	 *         是否同步:StringBuilder线程不同步 只支持单线程  线程不安全 效率高
	 *                 StringBuffer线程同步 支持多线程  线程安全 效率低
	 *                 
	 * 构造方法:
	 *     StringBuffer() :创建一个初始序列为空的字符串缓冲区对象
           StringBuffer(String str)  :创建一个与初始字符串相同序列的字符串缓冲区对象
      普通方法:
           和String相同的方法:
                     char charAt(int index)  :获取参数下标出的字符
                     int indexOf(String str) :获取参数字串第一次出现的位置 如果找不到返回-1
					 int indexOf(String str, int fromIndex)  :从fromIndex位置处开始 获取参数字串第一次出现的位置 如果找不到返回-1
					 int lastIndexOf(String str) :倒着找
					 int lastIndexOf(String str, int fromIndex)  
					 int length()  :获取字符个数
					 CharSequence subSequence(int start, int end) :截取字串:start到end-1处的字符
					 String substring(int start) :截取字串:start到末尾的字符
					 String substring(int start, int end)  截取字串:start到end-1处的字符
          字符串缓冲区特有的方法: 以下方法返回都是当前字符串缓冲区对象        
                     StringBuffer append(Object obj)  :把参数对象对应的字符串添加到末尾
                     StringBuffer delete(int start, int end):删除start到end-1处的字符 
					 StringBuffer deleteCharAt(int index)  :删除index下标出的字符
					 StringBuffer insert(int offset, Object obj) : 把obj对应的字符串插入到offset下标处
					 StringBuffer replace(int start, int end, String str) :使用str替换start到end-1位置处的子串 
					 StringBuffer reverse()  :字符串序列翻转
					 void setCharAt(int index, char ch):  设置index下标处的字符为ch
					 String toString():获取当前字符串缓冲区相同序列的字符串对象  
  • 练习
public static void main(String[] args) {
    StringBuilder stb=new StringBuilder("abcdefghijk");
    StringBuilder stb2=stb.append("lm");
    //append方法返回的是当前字符串缓冲区对象  可以实现方法链
    //stb.append("lm").append(1).append(2).append(true);
    System.out.println(stb==stb2);//true
    System.out.println(stb);//abcdefghijklm
    System.out.println(stb.delete(1, 3));//adefghijklm
    stb=new StringBuilder("abcdefghijk");
    System.out.println(stb.deleteCharAt(1));//acdefghijk
    stb=new StringBuilder("abcdefghijk");
    System.out.println(stb.insert(1, "haha"));//ahahabcdefghijk
    stb=new StringBuilder("abcdefghijkbc");
    System.out.println(stb.replace(1, 3, "123456"));//a123456defghijkbc
    System.out.println(stb.reverse());//cbkjihgfed654321a
    stb=new StringBuilder("abcdefghijk");
    stb.setCharAt(1, '0');
    System.out.println(stb);//a0cdefghijk

}
public static String change(String s){
    //使用字符串缓冲区实现字符串的转换:大小写转换 删除数字
    StringBuilder stb=new StringBuilder(s);//把字符串转换为字符串缓冲区
    for (int i = 0; i <stb.length(); i++) {
        //获取当前字符
        char c=stb.charAt(i);
        //判断当前字符的类型
        if(Character.isUpperCase(c)){
            c=Character.toLowerCase(c);
            stb.setCharAt(i, c);
        }else if(Character.isLowerCase(c)){
            c=Character.toUpperCase(c);
            stb.setCharAt(i, c);
        }else if(Character.isDigit(c)){
            //删除当前字符
            stb.deleteCharAt(i);
            i--;
        }
    }
    return stb.toString();
}

5 、LinkedList(重点)

/*
	 *LinkedList是List的实现类
	 *底层是链表
	 *使用和Arraylist基本相同 都可以根据下标操作元素  但提供了更多的对头和尾的操作
	 *   void addFirst(E e) :在头部添加元素
		 void addLast(E e) :在尾部添加元素 
		 E getFirst() :获取头部的第一个元素
		 E getLast() :获取尾部的最后一个元素
		 E pollFirst()  :移除并返回头部的第一个元素  如果链表为空 返回null
		 E pollLast()   :移除并返回尾部的最后一个元素  如果链表为空 返回null
		 E removeFirst() :移除并返回头部的第一个元素    如果链表为空 抛异常NoSuchElementException
		 E removeLast()  :移除并返回尾部的最后一个元素    如果链表为空 抛异常NoSuchElementException

	 LinkedList和ArrayList的区别
		 一: 底层实现不同:ArrayList底层是可变长度数组的实现  LinkedList底层是链表
		 二:	ArrayList元素在内存中是连续空间  而 LinkedList的元素内存空间可以不连续  可以实现内容的有效利用
		 三: ArrayList查询和修改效率高  但增删效率低  LinkedList增删效率高 但查询和修改效率低
	 * */
public static void main(String[] args) {
    LinkedList<String> list=new LinkedList<>();
    list.add("a");
    list.add("b");
    list.add("c");
    list.add("d");
    list.add("e");
    list.addFirst("0");
    list.addLast("1");
    for (int i = 0; i <list.size(); i++) {
        System.out.print(list.get(i)+(i==list.size()-1?"\n":","));
    }
}

5、TreeSet

  • 方法
	 * TreeSet: 不重复 元素按自然顺序排序
	 * 方法:继承与Collection
	 * 特有方法:
	 *      E first() :获取第一个元素
			E last() :获取最后一个元素 
		    E floor(E e)  :获取小于等于参数的最大元素 如果不存在这样的元素,则返回 null。
		    E ceiling(E e)  :获取大于等于参数的最小元素 如果不存在这样的元素,则返回 null。
		    E higher(E e)  :获取大于参数的最小元素  如果不存在这样的元素,则返回 null。
		    E lower(E e) :     获取小于参数的最大元素  如果不存在这样的元素,则返回 null。
		    E pollFirst(): 移除并返回第一个元素
		    E pollLast() :移除并返回最后一个元素 
  • 实现类的可比较性
package com.zhiyou100.day15_buchong;

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

public class Demo06TreeSet {
	/*

	*怎么保证一个类的对象具有可比较性:
	*    方案1: 让类实现Comparable<E>接口  实现public int compareTo(E o) 方法
	*    方案2:为类创建一个比较器类 实现Comparator<E> 实现public int compare(E o1, E o2)
	*          注意:在使用TreeSet时需要关联一个比较器对象:new TreeSet<>(new Student062Compartor());
	*	    
	 * */
	public static void main(String[] args) {
		 
		 TreeSet<Student06> set2=new TreeSet<>();
		 set2.add(new Student06("韩梅梅", 12, 17.8f));//java.lang.ClassCastException
		 set2.add(new Student06("韩庚", 22, 27.8f));
		 set2.add(new Student06("韩庚", 22, 27.8f));
		 set2.add(new Student06("韩雪", 32, 27.8f));
		 set2.add(new Student06("韩雪1", 32, 27.8f));
		 set2.add(new Student06("韩雪2", 32, 27.8f));
		 set2.add(new Student06("韩非子", 12, 17.8f));
		 set2.add(new Student06("韩信", 22, 27.8f));
		 
		 Iterator<Student06> it2=set2.iterator();
		 while(it2.hasNext()){
			 System.out.println(it2.next());
		 }
		 
		 
		 TreeSet<Student062> set3=new TreeSet<>(new Student062Compartor());
		 set3.add(new Student062("韩梅梅", 12, 17.8f));//java.lang.ClassCastException
		 set3.add(new Student062("韩庚", 22, 27.8f));
		 set3.add(new Student062("韩庚", 22, 27.8f));
		 set3.add(new Student062("韩雪", 32, 27.8f));
		 set3.add(new Student062("韩雪1", 32, 25.8f));
		 set3.add(new Student062("韩雪2", 32, 26.8f));
		 set3.add(new Student062("韩非子", 12, 17.8f));
		 set3.add(new Student062("韩信", 22, 27.8f));
		 set3.add(new Student062("韩信1", 22, 27.8f));
		 set3.add(new Student062("韩信2", 22, 27.8f));
		 
		 Iterator<Student062> it3=set3.iterator();
		 while(it3.hasNext()){
			 System.out.println(":::::::::"+it3.next());
		 }
	}
}
class Student06 implements Comparable<Student06>{
	String sname;
	int sage;
	float score;
	@Override
	public String toString() {
		return "Student06 [sname=" + sname + ", sage=" + sage + ", score=" + score + "]";
	}
	public Student06(String sname, int sage, float score) {
		this.sname = sname;
		this.sage = sage;
		this.score = score;
	}
	public Student06() {
		super();
	}
	//拿读取对象和参数对象做比较:当前对象大 返回正数 当前对象小 返回负数 相同返回0
	public int compareTo(Student06 o) {
		//按自己的要求返回:分数高的大  分数相同 年龄小的大  年龄相同 名字大的大
		if(o.score!=this.score){
			return this.score>o.score?1:-1;
		}
		if(o.sage!=this.sage){
			return o.sage-this.sage;
		}
		return this.sname.compareTo(o.sname);
	}
}

class Student062{
	String sname;
	int sage;
	float score;
	@Override
	public String toString() {
		return "Student06 [sname=" + sname + ", sage=" + sage + ", score=" + score + "]";
	}
	public Student062(String sname, int sage, float score) {
		this.sname = sname;
		this.sage = sage;
		this.score = score;
	}
}
class Student062Compartor implements Comparator<Student062>{
	@Override
	public int compare(Student062 o1, Student062 o2) {
		//年龄小的大  年龄相同  分数小的大  分数相同 名字小的大
		if(o1.sage!=o2.sage){
			return o1.sage-o2.sage;
		}
		if(o1.score!=o2.score){
			return o2.score<o1.score?1:-1;
		}
		return o1.sname.compareTo(o2.sname);
	}
}

6、集合工具类:Collections

/*
	 * Collections:集合工具类
	 *         提供了操作Collection的static方法
	 *         static  void  fill(List list, T obj)  : 使用参数对象obj替换list中的所有元素
               static  T   max(Collection coll) :获取最大的元素
               static  T   min(Collection coll) :获取最小的元素
               static  T max(Collection  coll, Comparator comp) :按制定比较器 获取最大的元素
               static  T min(Collection  coll, Comparator comp) :按制定比较器 获取最小的元素
               static void reverse(List<?> list) :反转 
               static void shuffle(List<?> list) :随机洗牌  
               static  void sort(List<T> list) :排序
               static  void sort(List<T> list, Comparator<? super T> c) :按参数比较器 排序
               static void swap(List<?> list, int i, int j)  :下标i和下标j处的元素互换位置
	 * */
	public static void main(String[] args) {
		   ArrayList   list=new ArrayList();
		   list.add("123");list.add("1");list.add("2");
		   list.add("abd");list.add("abc");list.add("abc");
		   show(list);
		   //Collections.fill(list, "abc");//使用abc替换list中的所有元素
		   //Collections.reverse(list);//集合元素反转
		   //Collections.shuffle(list);//洗牌
		   //Collections.sort(list);//排序
		   Collections.swap(list, 1, 2);//1 和 2 位置处的元素互换值
		   show(list);
	}
	public static void show(List list){
		for (int i = 0; i <list.size(); i++) {
			System.out.print(list.get(i)+(i==list.size()-1?"\n":","));
		}
	}

7、数组工具类:Arrays

 /*
     * Arrays:数组工具类:static操作数组的方法
	     * static <T> List<T>  asList(T... a):由参数数组获取一个集合
	     * static void fill(boolean[] a, boolean val) :使用val填充数组a
	       static void sort(char[] a)   :对数组a进行排序
	       static <T> void  sort(T[] a, Comparator<? super T> c) :按比较器c对数组a进行排序
	       static String toString(boolean[] a)  :获取参数数组的字符串
     * */
	public static void main(String[] args) {
		  String[] arr={"1a","12","1b","21","31","122"};
		  List<String> list=Arrays.asList(arr);
		  list=Arrays.asList("1a","12","1b","21","31","122");
		  show(list);
		  
		  System.out.println(Arrays.toString(arr));//[1a, 12, 1b, 21, 31, 122]

	}
	public static void show(List list){
		for (int i = 0; i <list.size(); i++) {
			System.out.print(list.get(i)+(i==list.size()-1?"\n":","));
		}
	}
  • 游戏:明7拍 暗7过
/*明7拍暗7过*/
//由n个猴子围成一圈,从1开始数数 数到7的倍数的猴子被踢出去  问最后的那个猴子是大王 他的编号是几
	public static int getDaiWang(int n){
		//定义一个boolean数组 装所有猴子
		Boolean[] arr=new Boolean[n];
		//把所有值转化为true
		Arrays.fill(arr, true);
		//定义变量记录被踢出去的猴子的个数
		int count=0;
		//定义变量记录叫的数
		int num=0;
		//一直遍历数组
		while(true){
			if(count==n-1){
				break;
			}
			for(int i=0;i<arr.length;i++){
				if(arr[i]){
					num++;//叫数
					if(num%7==0){
						//当前元素被踢出去
						arr[i]=false;
						count++;
						if(count==n-1){
							break;
						}
					}
				}
			}
			
		}
		//获取唯一的true
		List<Boolean> list=Arrays.asList(arr);
		int index1=list.indexOf(true)+1;
		//int index2=list.lastIndexOf(true)+1;
		//System.out.println(index1+"::"+index2);
		return index1;
		
	}

8、打印输出流:PrintWriter(重点)

  /*PrintWriter:打印输出流  
     * 特点1:既可以作为节点流还可以作为过滤流
     *      PrintWriter(File file) 
            PrintWriter(OutputStream out) 
            
     * 特点2:可以保证数据的原始状态
     *      pout.print(49);等价于 fout.write(49+"");
     *   
     * 特点3:当创建对象时指定自动刷新  调用println是可以实现自动刷新
     * 
     * */
	public static void main(String[] args)throws Exception {
		FileWriter fout=new FileWriter("src/com/zhiyou100/day15_buchong/1.txt");
		fout.write("abc");
		fout.write(49);//
		fout.write(true+"");
		//fout.flush();
		//fout.close();
		
		PrintWriter pout=new PrintWriter(new FileWriter("src/com/zhiyou100/day15_buchong/2.txt"),true);
		pout.println("abc");
		pout.println(49);
		pout.println(true);
		//pout.flush();
		//pout.close();
	}

9、序列化流(重点)

  • 介绍
     * 序列化相关的类:把内存中对象的信息持久化保存到硬盘中   把硬盘中的信息重构成内存中的对象
     * ObjectInputStream:反序列化流  把硬盘中的信息读到内存中 重构成对象 
     * ObjectOutputStream:序列化流:  把内存中对象的信息持久化保存到硬盘上
     * 
     * ObjectOutputStream类的方法:
     *   ObjectOutputStream(OutputStream out)  :构造方法关联一个字节流
     *   void writeObject(Object obj) :把一个对象的信息写到目的文件中 
     *   
     *ObjectInputStream类的方法:   
     *   ObjectInputStream(InputStream in):构造方法关联一个字节流
     *   Object readObject()  :一次读一个对象的信息 并重构对象
     *   
     * 
     * 注意事项:
     *    1 序列化流和反序列化流 操作的对象必须实现接口Serializable
     *    2 ObjectInputStreamd的readObject()读到文件末尾 抛出异常EOFException
     *    3 Serializable接口会给当前类分配一个唯一的编号  用于保证序列化和反序列化使用的同一个接口
     *    4 序列化流不支持续写
     * UUID:通用唯一识别码(Universally Unique Identifier)
     *      随机一个 32位的16进制的字符串   
  • 代码实现
	public static void main(String[] args)throws Exception{
//		for (int i = 0; i < 10; i++) {
//			System.out.println(UUID.randomUUID().toString());
//		}
		ArrayList<Student> list=new ArrayList<>();
//		for (int i = 0; i <10; i++) {
//			   list.add(new Student());
//		}
//		System.out.println(list);
//		saveObject(list,"src/com/zhiyou100/day15_buchong/student1.obj");
		
		createObject("src/com/zhiyou100/day15_buchong/student1.obj");
 
	}
	//把student1.obj中的信息重构成对象
	public static void createObject(String fileName)throws Exception{
		//1创建字节流关联源文件
		//2 创建反序列化流与节点流关联
		ObjectInputStream ois=new ObjectInputStream(new FileInputStream(fileName));
		//3 选择读的方式:逐个对象的读
		while(true){
			try{
				Student s=(Student)ois.readObject();
				System.out.print(s);
			}catch(EOFException e){
				break;
			}
		}
		//4关闭流
		ois.close();
	}
	//把list中的对象持久化保存到文件中
	public static void saveObject(ArrayList<Student> list,String fileName)throws Exception{
		//1 创建字节流关联目的文件
		FileOutputStream fout=new FileOutputStream(fileName);
		//2 创建序列化流与节点流关联
		ObjectOutputStream oos=new ObjectOutputStream(fout);
		//3 现在写方式:逐个对象的写
		for (Student s : list) {
			oos.writeObject(s);
		}
		
		//4关闭流
		oos.close();
//		[Student [sname=6cc4, sex=女, score=73.9]
//		, Student [sname=d476, sex=女, score=73.9]
//		, Student [sname=ba03, sex=男, score=52.4]
//		, Student [sname=f7f9, sex=女, score=54.3]
//		, Student [sname=5343, sex=女, score=48.4]
//		, Student [sname=bda8, sex=女, score=57.6]
//		, Student [sname=aef0, sex=男, score=68.8]
//		, Student [sname=1bc1, sex=女, score=59.9]
//		, Student [sname=e9c7, sex=男, score=84.6]
//		, Student [sname=e10f, sex=男, score=54.9]
	}
}
//Exception in thread "main" java.io.InvalidClassException: com.zhiyou100.day15_buchong.Student; local class incompatible: stream classdesc serialVersionUID = -5497088744421407018, local class serialVersionUID = -630471015205919448

class Student implements Serializable{
	//为当前类分配一个唯一编号
	private String sname;
	char sex;
	float score;
	public Student(){
		sname=UUID.randomUUID().toString().replace("-", "").substring(0, 4);
		sex=Math.random()>0.5?'男':'女';
		score=(int)(Math.random()*1001)/10.0f;
	}
	@Override
	public String toString() {
		return "Student [sname=" + sname + ", sex=" + sex + ", score=" + score + "]\n";
	}
}

10 、创建线程的方式

参考https://www.cnblogs.com/zhou-test/p/9811771.html

创建线程的四种方式

package com.zhiyou100.day15_buchong;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

public class Demo12CreateThread {
     public static void main(String[] args)throws Exception{
		 //test01();
		 //test02();
		 //test03();
		 //test04();

//    	 //1 创建runnbale接口的实现类
//    	 //2实现run方法
//    	 //3 创建线程池对象 并制定线程个数
//    	 ExecutorService threadPool=Executors.newFixedThreadPool(10);
//    	 //4 创建实现类对象
//    	 MyImp04 imp=new MyImp04();
//    	 //5 通过线程池对象的sumbit方法 提交线程任务:提交的次数 就是运行的线程个数
//    	 for (int i = 0; i <5; i++) {
//			threadPool.submit(imp);
//		 }
//    	 //6关闭池对象
//    	 threadPool.shutdown();
//    	 
//    	 
//    	 MyThread01  mt=new MyThread01();mt.setName("线程1111");
//    	 mt.start();
    	 
		 //未解决问题:把创建线程卸载方法中  main线程不能达到同步的效果
		 for (int i = 0; i < 50; i++) {
			 int n=(int)(Math.random()*10);
			 try {Thread.sleep(100);} catch (Exception e) {}
			 System.out.println(Thread.currentThread().getName()+"  :"+i+"::n="+n);
		 }
	 }
     //方式1: 继承Thread 重写run方法
     public static void test01(){
    	 MyThread01  mt=new MyThread01();mt.setName("线程1111");
    	 mt.start();
     }
     //方式2:实现Runnable接口  实现run方法
     public static void test02(){
    	 MyImp02 i2=new MyImp02();
    	 Thread t=new Thread(i2,"线程22222");
    	 t.start();
     }
     //方式3:实现Callable接口 实现call方法 创建FutureTask对象
     public static void test03()throws Exception{
    	 MyCall03  mc=new MyCall03();//创建callable实现类对象
    	 FutureTask<Integer>  task=new FutureTask<>(mc);//创建futuretask对象并关联callable实现类对象
    	 Thread t=new Thread(task);t.setName("线程3333333333");//创建线程对象 并关联futuretask对象
    	 t.start();//开启线程
    	 //获取线程的返回值
    	 int sum=task.get();
    	 System.out.println("sum="+sum);
     }
     //方式4:线程池: 线程池提供了一个线程队列,队列中保存着所有等待状态的线程。避免了创建与销毁额外开销,提交了响应速度。
     // 创建Runnable的实现类  通过Executors创建线程池对象  通过池对象的submit方法来启动一个线程
     public static void test04()throws Exception{
    	 //1 创建runnbale接口的实现类
    	 //2实现run方法
    	 //3 创建线程池对象 并制定线程个数
    	 ExecutorService threadPool=Executors.newFixedThreadPool(10);
    	 //4 创建实现类对象
    	 MyImp04 imp=new MyImp04();
    	 //5 通过线程池对象的sumbit方法 提交线程任务:提交的次数 就是运行的线程个数
    	 for (int i = 0; i <5; i++) {
			threadPool.submit(imp);
		 }
    	 //6关闭池对象
    	 threadPool.shutdown();
    	 
     }
     
     
}
class MyThread01 extends Thread{
	public void run(){
		for (int i = 0; i < 50; i++) {
			 int n=(int)(Math.random()*10);
			 try {Thread.sleep(100);} catch (Exception e) {}
			 System.out.println(Thread.currentThread().getName()+"  :"+i+"::n="+n);
		}
	}
}
class MyImp02 implements Runnable{
	public void run(){
		for (int i = 0; i < 50; i++) {
			 int n=(int)(Math.random()*10);
			 try {Thread.sleep(100);} catch (Exception e) {}
			 System.out.println(Thread.currentThread().getName()+"  :"+i+"::n="+n);
		}
	}
}
//实现Callable接口  接口的泛型是返回值类型
class MyCall03 implements Callable<Integer>{
	//1 可以有返回值  2 可以抛出异常
	public Integer call() throws Exception {
		int sum=0;
		for (int i = 0; i < 50; i++) {
			 int n=(int)(Math.random()*10); sum+=n;
			 try {Thread.sleep(100);} catch (Exception e) {}
			 System.out.println(Thread.currentThread().getName()+"  :"+i+"::n="+n);
		}
		return sum;
	}
}

class MyImp04 implements Runnable{
	public void run(){
		for (int i = 0; i < 50; i++) {
			 int n=(int)(Math.random()*10);
			 try {Thread.sleep(100);} catch (Exception e) {}
			 System.out.println(Thread.currentThread().getName()+" :::::"+i+"::n="+n);
		}
	}
}

11、 wait和notify

package com.zhiyou100.day15_buchong;

public class Demo13WaitNotify {
    /*
     * 面试题:wait和sleep的区别

     * wait和notify都是锁对象的方法
     * Object类的方法: void wait()    当前线程等待
     * Object类的方法: void notify()  随机唤醒一个当前对象作为锁对象 并且处于等待状态的线程
     * Object类的方法: void notifyAll()  唤醒所有当前对象作为锁对象 并且处于等待状态的线程
     *武大郎做烧饼  猪八戒吃烧饼 
     *1 实现做和吃不干扰::做和吃两个线程
     * */
	public static void main(String[] args) {
		
		// TODO Auto-generated method stub
		ShaoBing shb=new ShaoBing();
		Provider p1=new Provider(shb,"武大郎");
		Provider p2=new Provider(shb,"武二郎");
		Consumer c1=new Consumer(shb, "猪八戒");
		Consumer c2=new Consumer(shb, "沙僧");
		c1.start();
		c2.start();
				p1.start();
				p2.start();
	}
}
class ShaoBing{
	int num=0;
	boolean blag=false;//定义一个标签 记录当前是否有烧饼
}
class Provider extends Thread{
	ShaoBing shb;
	
	public Provider(ShaoBing shb,String name) {
		super(name);
		this.shb = shb;
	}

	public void run(){
		while(true){
			synchronized (shb) {
				if(shb.blag==false){
					System.out.println(Thread.currentThread().getName()+"开始做烧饼::"+(shb.num+1));
					shb.num++;
					try {Thread.sleep(200);} catch (Exception e) {}
					System.out.println(Thread.currentThread().getName()+"做完烧饼::"+(shb.num));
					//提醒猪八戒 可以吃烧饼
					shb.blag=true;
					shb.notifyAll();//唤醒猪八戒:唤醒一个shb相同锁 并且处于等待状态的线程
				}else{
					try {shb.wait();} catch (Exception e) {}//当前线程等待
				}
			}
			try {Thread.sleep(20);} catch (Exception e) {}
		}
	}
}
class Consumer extends Thread{
	ShaoBing shb;
	public Consumer(ShaoBing shb,String name) {
		super(name);
		this.shb = shb;
	}
	public void run(){
		while(true){
			synchronized (shb) {
				if(shb.blag){
					System.out.println(Thread.currentThread().getName()+"开始吃烧饼::::::"+(shb.num));
					try {Thread.sleep(20);} catch (Exception e) {}
					System.out.println(Thread.currentThread().getName()+"吃烧饼完成::::::"+(shb.num));
					shb.blag=false;//烧饼标签值更改
					shb.notifyAll();//唤醒武大郎
				}else{
					try {shb.wait();} catch (Exception e) {}//当前线程等待
				}
			}
			try {Thread.sleep(20);} catch (Exception e) {}
		}
	}
}
posted @ 2021-09-10 17:36  RenVei  阅读(37)  评论(0编辑  收藏  举报