线程之间的通信

主要是三个方法wait(); notify(); notifyAll()

wait()使当前线程阻塞,前提是 必须先获得锁,一般配合synchronized 关键字使用,即,一般在synchronized 同步代码块里使用 wait()、notify/notifyAll() 方法。

wait方法释放锁, notify方法不释放锁

由于 wait()、notify/notifyAll() 在synchronized 代码块执行,说明当前线程一定是获取了锁的。
当线程执行wait()方法时候,会释放当前的锁,然后让出CPU,进入等待状态。
只有当 notify/notifyAll() 被执行时候,才会唤醒一个或多个正处于等待状态的线程,然后继续往下执行,直到执行完synchronized 代码块的代码或是中途遇到wait() ,再次释放锁。
 
notify方法只唤醒一个等待(对象的)线程并使该线程开始执行。所以如果有多个线程等待一个对象,这个方法只会唤醒其中一个线程,选择哪个线程取决于操作系统对多线程管理的实现。notifyAll 会唤醒所有等待(对象的)线程,尽管哪一个线程将会第一个处理取决于操作系统的实现。
 
wait(), notify(), notifyAll() 必须是同一对象的多个线程之间的通信
举例
 
Target1
 1 public class Target1 implements Runnable {
 2 
 3     private Demo3 demo;
 4 
 5     public Target1(Demo3 demo) {
 6         this.demo = demo;
 7     }
 8 
 9     @Override
10     public void run() {
11         demo.set();
12     }
13 
14 }

Target2

 1 public class Target2 implements Runnable {
 2 
 3     private Demo3 demo;
 4 
 5     public Target2(Demo3 demo) {
 6         this.demo = demo;
 7     }
 8 
 9     @Override
10     public void run() {
11         demo.get();
12     }
13 
14 }

Demo3

public class Demo3 {

    private volatile int signal;

    public synchronized void set () {
        signal = 1;
        notifyAll(); // notify方法会随机叫醒一个处于wait状态的线程
        // notifyAll叫醒所有的处于wait线程,争夺到时间片的线程只有一个
        System.out.println("叫醒线程叫醒之后休眠开始...");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public synchronized int get () {
        System.out.println(Thread.currentThread().getName() + " 方法执行了...");
        if(signal != 1) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(Thread.currentThread().getName() + " 方法执行完毕...");
        return signal;
    }

    public static void main(String[] args) {

        Demo3 d = new Demo3();
        Target1 t1 = new Target1(d);
        Target2 t2 = new Target2(d);

        new Thread(t2).start();
        new Thread(t2).start();
        new Thread(t2).start();
        new Thread(t2).start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(t1).start();

    }
}

Console

hread-0 方法执行了...
Thread-2 方法执行了...
Thread-1 方法执行了...
Thread-3 方法执行了...
叫醒线程叫醒之后休眠开始...
Thread-3 方法执行完毕...
Thread-1 方法执行完毕...
Thread-2 方法执行完毕...
Thread-0 方法执行完毕...

生产者和消费者问题

Tmall

 1 public class Tmall {
 2     private int count;
 3 
 4     public final int MAX_COUNT = 10;
 5 
 6     public synchronized void  push(){
 7         while (count >= MAX_COUNT){
 8             try {
 9                 System.out.println(Thread.currentThread().getName()+"生产者库存数量库存满,生产者停止生产");
10                 wait();
11             } catch (InterruptedException e) {
12                 e.printStackTrace();
13             }
14         }
15         count++;
16         System.out.println(Thread.currentThread().getName()+"生产者生产,当前库存为:"+count);
17         notifyAll();
18     }
19 
20 
21 
22     public synchronized void take(){
23         while (count<= 0){
24             try {
25                 System.out.println(Thread.currentThread().getName()+"生产者库存数量库0,消费者等待");
26                 wait();
27             } catch (InterruptedException e) {
28                 e.printStackTrace();
29             }
30         }
31 
32         count--;
33         System.out.println(Thread.currentThread().getName()+"生产者消费,当前库存为:"+count);
34         notifyAll();
35 
36     }

TakeTarget

 1 public class TakeTarget implements  Runnable{
 2 
 3     private Tmall tmall;
 4 
 5     public TakeTarget(Tmall tmall){
 6         this.tmall = tmall;
 7     }
 8 
 9 
10     @Override
11     public void run() {
12 
13        while (true){
14            tmall.take();
15            try {
16                Thread.sleep(1000);
17            } catch (InterruptedException e) {
18                e.printStackTrace();
19            }
20        }
21 
22     }
23 }

PushTarget

 1 public class PushTarget  implements Runnable{
 2 
 3     private Tmall tmall;
 4 
 5     public PushTarget(Tmall tmall){
 6         this.tmall = tmall;
 7     }
 8 
 9 
10     @Override
11     public void run() {
12         while (true){
13             tmall.push();
14             try {
15                 Thread.sleep(1000);
16             } catch (InterruptedException e) {
17                 e.printStackTrace();
18             }
19         }
20     }
21 }

Main

    public static void main(String[] args) {

        Tmall tmall = new Tmall();

        PushTarget p = new PushTarget(tmall);

        TakeTarget t = new TakeTarget(tmall);

        new Thread(p).start();
        new Thread(p).start();
        new Thread(p).start();
        new Thread(p).start();


        new Thread(t).start();
        new Thread(t).start();
        new Thread(t).start();
    }

}

生产者线程多余消费者线程

Console

Thread-6生产者消费,当前库存为:9
Thread-0生产者生产,当前库存为:10
Thread-1生产者库存数量库存满,生产者停止生产..................

 
 
 
 
原文地址:https://www.cnblogs.com/quyangyang/p/11184215.html