Java学习之线程间通讯(双线程)

线程间通讯:多个线程在处理同一资源,但是任务不同

练习一:双线程出现线程安全问题,需要使用同步,思考同步代码添加位置
需求:银行账户存钱,显示谁在账户存钱了,存了多少钱
分析:
操作同一银行账户
两个不同的操作,一个是存,一个是显示
这个两个操作可以同时执行

代码:

 1 class Bank
 2 {
 3     String name;//存钱人名
 4     int amount;
 5     
 6     //无论是存还是取应该都是银行的动作
 7     void put(String name,int amount)
 8     {
 9         this.name=name;
10         this.amount=amount;
11     }
12     
13     void take()
14     {
15         System.out.println(this.name+"---"+this.amount);
16     }
17 }
18 //定义对象实现Runnable,设置线程任务
19 class Input implements Runnable
20 {
21     private Bank b;
22     //使用构造函数保证存钱和显示同一资源
23     public Input(Bank b)
24     {
25         this.b=b;
26     }
27     public void run()
28     {
29         int x=0;
30         while(true)
31         {
32             if(x==0)
33             {
34                 b.put("张三",100);
35             }
36             else
37             {
38                 b.put("lisi",200);
39             }
40             //0与1之间切换可使用求2的余数
41             x=(x+1)%2;
42         }
43     }
44 }
45 
46 //定义对象实现Runnable,设置线程任务
47 class Output implements Runnable
48 {
49     private Bank b;
50     //使用构造函数保证存钱和显示同一资源
51     public Output(Bank b)
52     {
53         this.b=b;
54     }
55     public void run()
56     {
57         while(true)
58         {
59             b.take();
60         }
61     }
62 }
63 
64 class ThreadDemo
65 {
66     public static void main (String[] args)
67     {
68         //同一资源
69         Bank b=new Bank();
70         
71         Input in=new Input(b);
72         Output out=new Output(b);
73         
74         //
75         Thread t1=new Thread(in);
76         Thread t2=new Thread(out);
77         
78         t1.start();
79         t2.start();
80     }
81 }

结果:

出现线程安全,为什么呢?

分析:

 解决方法:添加同步(synchronized),同步要添加到什么位置

添加同步锁的原则:有共享数据被操作的代码上,且同步锁对象要相同(同步方法的同步锁为,此类的对象(this))

代码:

 1 class Bank
 2 {
 3     String name;//存钱人名
 4     int amount;
 5     
 6     //同步方法的同步锁为,此类的对象(this)
 7     synchronized void put(String name,int amount)
 8     {
 9         this.name=name;
10         this.amount=amount;
11     }
12     
13     synchronized void take()
14     {
15         System.out.println(this.name+"---"+this.amount);
16     }
17 }

结果出现的效果与预想结果不同,预想结果是存一笔,显示一笔

结果分析:

 接下来,想法是:在t1中执行完成后就让t2执行

具体做法:

1、使用一个共享数据(flag)记录t1是否已执行

2、已执行就让t1等待(原因:防止t1再次获取CPU执行权),让t2执行

3、t2执行完成,t2等待,把t1设置成未执行状态(让t1获取CPU执行资格)

 1 class Bank
 2 {
 3     private String name;
 4     private int amount;
 5     private boolean flag=false;
 6     
 7     synchronized void put(String name,int amount)
 8     {
 9         //1、判断线程是否已执行,防止t1线程继续获取CUP执行权
10         if(flag)
11             try{this.wait();}catch(InterruptedException e){}//wait()方法,将线程存放在阻塞线程池中,释放CUP执行权和释放同步锁
12             
13         this.name=name;
14         this.amount=amount;
15         //已执行赋值
16         this.flag = true;
17         //唤醒阻塞线程池中的第一个线程,获取CUP执行资格
18         this.notify();
19     }
20     
21     synchronized void take()
22     {
23         if(!flag)
24             try{this.wait();}catch(InterruptedException e){}
25         System.out.println(this.name+"---"+this.amount);
26         
27         this.flag = false;
28         this.notify();
29     }
30 }

结果:

猜你喜欢

转载自www.cnblogs.com/WarBlog/p/12074056.html