多线程基础回顾(三)-线程通信

生产-消费

规则

  • 当库存大于库容时,生产者停止生产,消费者开始消费。
  • 当库存小于等于0时,消费者停止消费,生产者开始生产。
  1. 定义一个仓库

 1 class Storehouse {
 2     //库容
 3     private int max = 20;
 4     //当前库存
 5     private int currentCount = 0;
 6     public  void provide(){
 7         currentCount++;
 8         System.out.println(Thread.currentThread().getName()+"生产1个,剩余:"+currentCount);
 9     }
10     
11     public  void consume(){
12         currentCount--;
13         System.out.println(Thread.currentThread().getName()+"消费1个,剩余:"+currentCount);
14     }
15 
16     public int getMax() {
17         return max;
18     }
19 
20     public int getCurrentCount() {
21         return currentCount;
22     }
23 }

 

  1. 生产者类

 1 class Provider implements Runnable{
 2     private Storehouse house;
 3     
 4     public Provider(Storehouse house) {
 5         this.house = house;
 6     }
 7     @Override
 8     public void run() {
 9         synchronized (house) {
10             while(true){
11                 if(house.getCurrentCount() >= house.getMax()){
12                     try {
13                         System.out.println("请求消费");
14                         house.notify();
15                         house.wait();
16                     } catch (InterruptedException e) {
17                         e.printStackTrace();
18                     }
19                 }else{
20                     try {
21                         Thread.sleep(500);
22                     } catch (InterruptedException e) {
23                         e.printStackTrace();
24                     }
25                     house.provide();
26                 }
27             }
28         }
29     }
30     
31 }

 

  1. 消费者类

 1 class Consumer implements Runnable{
 2     private Storehouse house;
 3     public Consumer(Storehouse house) {
 4         this.house = house;
 5     }
 6     @Override
 7     public void run() {
 8         synchronized (house) {
 9             while(true){
10                 if(house.getCurrentCount()<=0){
11                     try {
12                         System.out.println("请求生产");
13                         house.notify();
14                         house.wait();
15                     } catch (InterruptedException e) {
16                         e.printStackTrace();
17                     }
18                 }else{
19                     try {
20                         Thread.sleep(1000);
21                     } catch (InterruptedException e) {
22                         e.printStackTrace();
23                     }
24                     house.consume();
25                     
26                 }
27             }
28         }
29 
30     }
31     
32 }

 

  1. 测试类

 1 public class ThreadTest{
 2     public static void main(String[] args) {
 3         Storehouse house = new Storehouse();
 4         Provider p = new Provider(house);
 5         Consumer c = new Consumer(house);
 6         Thread th;
 7         th = new Thread(p,"工人");
 8         th.start();
 9         th = new Thread(c,"顾客");
10         th.start();
11     }
12 }

 

线程通信主要通过一个共享对象,此处Storehouse便作为共享对象,作为两个runable实例的共享锁,通过Storehouse.wait()使当前持有它的线程进入等待状态,通过Storehouse.notify唤醒某条拥有该锁的等待线程。

注意事项

  • sleep()和yield()的区别:sleep()使当前线程进入停滞状态,所以执行sleep()的线程在指定的时间内肯定不会被执行;yield()只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行;

  • interrupt():不要以为它是中断某个线程!它只是线线程发送一个中断信号,让线程在无限等待时(如死锁时)能抛出抛出,从而结束线程,但是如果你吃掉了这个异常,那么这个线程还是不会中断的;

  • Obj.wait(),与Obj.notify()必须要与synchronized(Obj)一起使用,也就是wait,与notify是针对已经获取了Obj锁进行操作,从语法角度来说就是Obj.wait(),Obj.notify必须在synchronized(Obj){...}语句块内;

  • obj.wait()与obj.sleep()区别: sleep方法没有释放锁,而wait方法释放了锁;wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用; wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用;

posted @ 2019-01-23 16:17  哈比Sport  阅读(104)  评论(0编辑  收藏  举报