Java中的wait/notify/notifyAll可用來實現線程間通信,是Object類的方法,這三個方法都是native方法,是平臺相關的,常用來實現生產者/消費者模式。先來我們來看下相關定義:
- wait() :調用該方法的線程進入WATTING狀態,只有等待另外線程的通知或中斷才會返回,調用wait()方法后,會釋放對象的鎖。
- wait(long):超時等待最多long毫秒,如果沒有通知就超時返回。
- notify() : 通知一個在對象上等待的線程,使其從wait()方法返回,而返回的前提是該線程獲取到了對象的鎖。
- notifyAll():通知所有等待在該對象上的線程。
實例代碼
class ThreadA extends Thread{
public ThreadA(String name) {
super(name);
}
public void run() {
synchronized (this) {
try {
Thread.sleep(1000); // 使當前線阻塞 1 s,確保主程序的 t1.wait(); 執行之后再執行 notify()
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" call notify()");
// 喚醒當前的wait線程
this.notify();
}
}
}
public class WaitTest {
public static void main(String[] args) {
ThreadA t1 = new ThreadA("t1");
synchronized(t1) {
try {
// 啟動“線程t1”
System.out.println(Thread.currentThread().getName()+" start t1");
t1.start();
// 主線程等待t1通過notify()喚醒。
System.out.println(Thread.currentThread().getName()+" wait()");
t1.wait(); // 不是使t1線程等待,而是當前執行wait的線程等待
System.out.println(Thread.currentThread().getName()+" continue");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
LinkedBlockingQueue 實現
public class Consumer extends Thread {
private Storage storage;
public Consumer(Storage storage) {
this.storage = storage;
}
@Override
public void run() {
while (true) {
try {
Storage.Goods goods = storage.goods.take();
System.out.printf(String.valueOf(storage.goods.size())+"\\n");
Thread.sleep(300);
System.out.println("消費" + " " + goods.getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Producer extends Thread {
private Storage storage;
private int i = 0;
public Producer(Storage storage) {
this.storage = storage;
}
@Override
public void run() {
while (true) {
try {
storage.goods.put(new Storage.Goods("蘋果"+ i));
Thread.sleep(100);
i++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Storage {
public static int MAX_COUNT = 5; //容量為5
public BlockingQueue<Goods> goods = new LinkedBlockingQueue<Goods>(MAX_COUNT);
public Storage() {
}
public static class Goods {
int id;
String name;
public Goods(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
public class TestThread {
public static Object obj = new Object();
public static void main(String[] args) throws InterruptedException {
ExecutorService service = Executors.newCachedThreadPool();
Storage storage = new Storage();
Consumer consumer1 = new Consumer(storage);
Consumer consumer2 = new Consumer(storage);
Producer producer = new Producer(storage);
service.submit(consumer1);
service.submit(consumer2);
service.submit(producer);
}
}