wait/notifyAll实现
public class ProductorConsumer { public static void main(String[] args) { LinkedList linkedList = new LinkedList(); ExecutorService service = Executors.newFixedThreadPool(15); for (int i = 0; i < 5; i++) { service.submit(new Productor(linkedList, 8)); } for (int i = 0; i < 10; i++) { service.submit(new Consumer(linkedList)); } } static class Productor implements Runnable { private List<Integer> list; private int maxLength; public Productor(List list, int maxLength) { this.list = list; this.maxLength = maxLength; } @Override public void run() { while (true) { synchronized (list) { try { while (list.size() == maxLength) { System.out.println("生产者" + Thread.currentThread().getName() + " list以达到最大容量,进行wait"); list.wait(); System.out.println("生产者" + Thread.currentThread().getName() + " 退出wait"); } Random random = new Random(); int i = random.nextInt(); System.out.println("生产者" + Thread.currentThread().getName() + " 生产数据" + i); list.add(i); list.notifyAll(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } static class Consumer implements Runnable { private List<Integer> list; public Consumer(List list) { this.list = list; } @Override public void run() { while (true) { synchronized (list) { try { while (list.isEmpty()) { System.out.println("消费者" + Thread.currentThread().getName() + " list为空,进行wait"); list.wait(); System.out.println("消费者" + Thread.currentThread().getName() + " 退出wait"); } Integer element = list.remove(0); System.out.println("消费者" + Thread.currentThread().getName() + " 消费数据:" + element); list.notifyAll(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } }
输出如下:
生产者pool-1-thread-1 生产数据-232820990 生产者pool-1-thread-1 生产数据1432164130 生产者pool-1-thread-1 生产数据1057090222 生产者pool-1-thread-1 生产数据1201395916 生产者pool-1-thread-1 生产数据482766516 生产者pool-1-thread-1 list以达到最大容量,进行wait 消费者pool-1-thread-15 退出wait 消费者pool-1-thread-15 消费数据:1237535349 消费者pool-1-thread-15 消费数据:-1617438932 消费者pool-1-thread-15 消费数据:-535396055 消费者pool-1-thread-15 消费数据:-232820990 消费者pool-1-thread-15 消费数据:1432164130 消费者pool-1-thread-15 消费数据:1057090222 消费者pool-1-thread-15 消费数据:1201395916 消费者pool-1-thread-15 消费数据:482766516 消费者pool-1-thread-15 list为空,进行wait 生产者pool-1-thread-5 退出wait 生产者pool-1-thread-5 生产数据1442969724 生产者pool-1-thread-5 生产数据1177554422 生产者pool-1-thread-5 生产数据-133137235 生产者pool-1-thread-5 生产数据324882560 生产者pool-1-thread-5 生产数据2065211573 生产者pool-1-thread-5 生产数据253569900 生产者pool-1-thread-5 生产数据571277922 生产者pool-1-thread-5 生产数据1622323863 生产者pool-1-thread-5 list以达到最大容量,进行wait 消费者pool-1-thread-10 退出wait
使用BlockingQueue实现
由于BlockingQueue内部实现就附加了两个阻塞操作。即当队列已满时,阻塞向队列中插入数据的线程,直至队列中未满;当队列为空时,阻塞从队列中获取数据的线程,直至队列非空时为止。
public class ProductorConsumer { private static LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>(); public static void main(String[] args) { ExecutorService service = Executors.newFixedThreadPool(15); for (int i = 0; i < 5; i++) { service.submit(new Productor(queue)); } for (int i = 0; i < 10; i++) { service.submit(new Consumer(queue)); } } static class Productor implements Runnable { private BlockingQueue queue; public Productor(BlockingQueue queue) { this.queue = queue; } @Override public void run() { try { while (true) { Random random = new Random(); int i = random.nextInt(); System.out.println("生产者" + Thread.currentThread().getName() + "生产数据" + i); queue.put(i); } } catch (InterruptedException e) { e.printStackTrace(); } } } static class Consumer implements Runnable { private BlockingQueue queue; public Consumer(BlockingQueue queue) { this.queue = queue; } @Override public void run() { try { while (true) { Integer element = (Integer) queue.take(); System.out.println("消费者" + Thread.currentThread().getName() + "正在消费数据" + element); } } catch (InterruptedException e) { e.printStackTrace(); } } } }
输出如下:
消费者pool-1-thread-7正在消费数据1520577501 生产者pool-1-thread-4生产数据-127809610 消费者pool-1-thread-8正在消费数据504316513 生产者pool-1-thread-2生产数据1994678907 消费者pool-1-thread-11正在消费数据1967302829 生产者pool-1-thread-1生产数据369331507 消费者pool-1-thread-9正在消费数据1994678907 生产者pool-1-thread-2生产数据-919544017 消费者pool-1-thread-12正在消费数据-127809610 生产者pool-1-thread-4生产数据1475197572 消费者pool-1-thread-14正在消费数据-893487914 生产者pool-1-thread-3生产数据906921688 消费者pool-1-thread-6正在消费数据-1292015016 生产者pool-1-thread-5生产数据-652105379 生产者pool-1-thread-5生产数据-1622505717 生产者pool-1-thread-3生产数据-1350268764 消费者pool-1-thread-7正在消费数据906921688 生产者pool-1-thread-4生产数据2091628867 消费者pool-1-thread-13正在消费数据1475197572 消费者pool-1-thread-15正在消费数据-919544017 生产者pool-1-thread-2生产数据564860122 生产者pool-1-thread-2生产数据822954707 消费者pool-1-thread-14正在消费数据564860122 消费者pool-1-thread-10正在消费数据369331507 生产者pool-1-thread-1生产数据-245820912 消费者pool-1-thread-6正在消费数据822954707 生产者pool-1-thread-2生产数据1724595968 生产者pool-1-thread-2生产数据-1151855115 消费者pool-1-thread-12正在消费数据2091628867 生产者pool-1-thread-4生产数据-1774364499 生产者pool-1-thread-4生产数据2006106757 消费者pool-1-thread-14正在消费数据-1774364499 生产者pool-1-thread-3生产数据-1070853639 消费者pool-1-thread-9正在消费数据-1350268764 消费者pool-1-thread-11正在消费数据-1622505717 生产者pool-1-thread-5生产数据355412953
补充
- wait()和sleep()的区别
- sleep(),是属于Thread类中的;wait(),则是属于Object类中的。
- sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。在调用sleep()方法的过程中,线程不会释放对象锁。而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。
- 在调用 wait()之前,线程必须要获得该对象的对象监视器锁,即只能在同步方法或同步块中调用 wait()方法。如果调用wait()方法时,线程并未获取到锁的话,则会抛出IllegalMonitorStateException异常。
- 唤醒条件,对于wait(),其他线程调用对象的notify()或者notifyAll()方法;对于sleep(),超时或者调用interrupt()方法
来源:https://www.cnblogs.com/xiaobingzi/p/10751049.html