- 线程通信是用来解决生产者消费者问题的;
- 生产者消费者样例:
// 工作台 class Workbench{ private static final int MAX = 10; private volatile int count = 0; public synchronized void put(){ while (count >= MAX){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } count++; try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "放了一个资源,工作台上还有" + count + "个资源."); notifyAll(); } public synchronized void take(){ while (count <= 0){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } count--; try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "拿走了一个资源,工作台上还有" + count + "个资源."); notifyAll(); } } // 生产者 class Producer extends Thread{ private Workbench workbench; public Producer(String name, Workbench workbench) { super(name); this.workbench = workbench; } @Override public void run() { while (true){ workbench.put(); } } } // 消费者 class Customer extends Thread{ private Workbench workbench; public Customer(String name, Workbench workbench) { super(name); this.workbench = workbench; } @Override public void run() { while (true){ workbench.take(); } } } // 主线程 public class ThreadCommunication { public static void main(String[] args) { Workbench workbench = new Workbench(); Producer producer1 = new Producer("生产者1",workbench); Producer producer2 = new Producer("生产者2",workbench); Customer customer1 = new Customer("消费者1",workbench); Customer customer2 = new Customer("消费者2",workbench); Customer customer3 = new Customer("消费者3",workbench); producer1.start(); producer2.start(); customer1.start(); customer2.start(); customer3.start(); } }
注意:
1) wait()方法和notify()方法是Object类中声明的方法不是Thread类;
2) wait()方法和notify()方法都必须由锁对象来进行调用,如果不写默认是this;
3) 可能会有一个异常java.lang.IllegalMonitorStateException说明调用wait()方法和notify()方法的对象不正确;
4) notify()方法只能唤醒同一个锁对象下的某一个正在等待的线程;
5) notify()方法和notifyAll()方法的区别:当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。也就是说,调用了notify后只要一个线程会由等待池进入锁池,而notifyAll会将该对象等待池内的所有线程移动到锁池中,等待锁竞争;
6)当有多个生产者和多个消费者时候要注意用while代替if做判断确保线程被唤醒后会重新判断执行条件;
7)当多个生产者多个消费者时,用notifyAll()方法代替notify()方法,避免死锁;
声明:本文章是自学后编写,仅供参考,如有疏漏之处感谢指正;