1 //代码中的实体类
2 public classStudent {3 String name;4 intage;5 boolean flag; //默认情况是没有数据,如果是true,说明有数据
6 }7
8 public class SetThread implementsRunnable {9
10 privateStudent s;11 private int x = 0;12
13 publicSetThread(Student s) {14 this.s =s;15 }16
17 @Override18 public voidrun() {19 while (true) {20 synchronized(s) {21 //判断有没有
22 if(s.flag){23 try{24 s.wait(); //t1等着,释放锁
25 } catch(InterruptedException e) {26 e.printStackTrace();27 }28 }29
30 if (x % 2 == 0) {31 s.name = "林青霞";32 s.age = 27;33 } else{34 s.name = "刘意";35 s.age = 30;36 }37 x++; //x=138
39 //修改标记
40 s.flag = true;41 //唤醒线程
42 s.notify(); //唤醒t2,唤醒并不表示你立马可以执行,必须还得抢CPU的执行权。
43 }44 //t1有,或者t2有
45 }46 }47 }48
49 public class GetThread implementsRunnable {50 privateStudent s;51
52 publicGetThread(Student s) {53 this.s =s;54 }55
56 @Override57 public voidrun() {58 while (true) {59 synchronized(s) {60 if(!s.flag){61 try{62 s.wait(); //t2就等待了。立即释放锁。将来醒过来的时候,是从这里醒过来的时候
63 } catch(InterruptedException e) {64 e.printStackTrace();65 }66 }67
68 System.out.println(s.name + "---" +s.age);69 //林青霞---2770 //刘意---3071
72 //修改标记
73 s.flag = false;74 //唤醒线程
75 s.notify(); //唤醒t1
76 }77 }78 }79 }80
81 /*
82 * 分析:83 * 资源类:Student84 * 设置学生数据:SetThread(生产者)85 * 获取学生数据:GetThread(消费者)86 * 测试类:StudentDemo87 *88 * 问题1:按照思路写代码,发现数据每次都是:null---089 * 原因:我们在每个线程中都创建了新的资源,而我们要求的时候设置和获取线程的资源应该是同一个90 * 如何实现呢?91 * 在外界把这个数据创建出来,通过构造方法传递给其他的类。92 *93 * 问题2:为了数据的效果好一些,我加入了循环和判断,给出不同的值,这个时候产生了新的问题94 * A:同一个数据出现多次95 * B:姓名和年龄不匹配96 * 原因:97 * A:同一个数据出现多次98 * CPU的一点点时间片的执行权,就足够你执行很多次。99 * B:姓名和年龄不匹配100 * 线程运行的随机性101 * 线程安全问题:102 * A:是否是多线程环境 是103 * B:是否有共享数据 是104 * C:是否有多条语句操作共享数据 是105 * 解决方案:106 * 加锁。107 * 注意:108 * A:不同种类的线程都要加锁。109 * B:不同种类的线程加的锁必须是同一把。110 *111 * 问题3:虽然数据安全了,但是呢,一次一大片不好看,我就想依次的一次一个输出。112 * 如何实现呢?113 * 通过Java提供的等待唤醒机制解决。114 *115 * 等待唤醒:116 * Object类中提供了三个方法:117 * wait():等待118 * notify():唤醒单个线程119 * notifyAll():唤醒所有线程120 * 为什么这些方法不定义在Thread类中呢?121 * 这些方法的调用必须通过锁对象调用,而我们刚才使用的锁对象是任意锁对象。122 * 所以,这些方法必须定义在Object类中。123 */
124 public classStudentDemo {125 public static voidmain(String[] args) {126 //创建资源
127 Student s = newStudent();128
129 //设置和获取的类
130 SetThread st = newSetThread(s);131 GetThread gt = newGetThread(s);132
133 //线程类
134 Thread t1 = newThread(st);135 Thread t2 = newThread(gt);136
137 //启动线程
138 t1.start();139 t2.start();140 }141 }