java编程思想笔记-并发之线程协作(二)
来源:互联网 发布:大华onvif协议端口 编辑:程序博客网 时间:2024/06/14 08:25
notify()与notifyAll()使用条件
1.使用notify()在众多等待同一个锁的任务只有一个被唤醒
2.使用notifyAll(),只会唤醒希望持有当前锁的所有线程
package com.tij.thread.cooperate;import java.util.Timer;import java.util.TimerTask;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.TimeUnit;class Blocker { synchronized void waitingCall() { try { while (!Thread.interrupted()) { wait(); System.out.println(Thread.currentThread() + " "); } } catch (Exception e) { System.err.println("WaitingCall Interrupted Exception !!!"); } } synchronized void prod() { notify(); } synchronized void prodAll() { notifyAll(); }}class Task implements Runnable { static Blocker blocker = new Blocker(); @Override public void run() { blocker.waitingCall(); }}class Task2 implements Runnable { static Blocker blocker = new Blocker(); @Override public void run() { blocker.waitingCall(); }}public class NotifyVsNotifyAll { public static void main(String[] args) throws InterruptedException { ExecutorService exec=Executors.newCachedThreadPool(); //每个Task线程都会因为blocker而阻塞 for (int i = 0; i < 5; i++) { exec.execute(new Task()); } exec.execute(new Task2()); Timer timer=new Timer(); timer.scheduleAtFixedRate(new TimerTask() { boolean prod=true; @Override public void run() { if (prod) { System.out.println("\nnotify()"); Task.blocker.prod(); prod=false; }else { System.out.println("\nnotifyAll()"); Task.blocker.prodAll(); prod=true; } } }, 400, 400); TimeUnit.SECONDS.sleep(5); timer.cancel(); System.out.println("\nTimer canceled "); TimeUnit.MILLISECONDS.sleep(500); System.out.println("Task2.blocker.prodAll()"); Task2.blocker.prodAll(); TimeUnit.MILLISECONDS.sleep(500); System.out.println("\nShutting down"); exec.shutdownNow(); }}
运行结果:
notify()Thread[pool-1-thread-1,5,main] notifyAll()Thread[pool-1-thread-1,5,main] Thread[pool-1-thread-5,5,main] Thread[pool-1-thread-4,5,main] Thread[pool-1-thread-3,5,main] Thread[pool-1-thread-2,5,main] notify()Thread[pool-1-thread-1,5,main] notifyAll()Thread[pool-1-thread-1,5,main] Thread[pool-1-thread-2,5,main] Thread[pool-1-thread-3,5,main] Thread[pool-1-thread-4,5,main] Thread[pool-1-thread-5,5,main] notify()Thread[pool-1-thread-1,5,main] notifyAll()Thread[pool-1-thread-1,5,main] Thread[pool-1-thread-5,5,main] Thread[pool-1-thread-4,5,main] Thread[pool-1-thread-3,5,main] Thread[pool-1-thread-2,5,main] notify()Thread[pool-1-thread-1,5,main] notifyAll()Thread[pool-1-thread-1,5,main] Thread[pool-1-thread-2,5,main] Thread[pool-1-thread-3,5,main] Thread[pool-1-thread-4,5,main] Thread[pool-1-thread-5,5,main] notify()Thread[pool-1-thread-1,5,main] notifyAll()Thread[pool-1-thread-1,5,main] Thread[pool-1-thread-5,5,main] Thread[pool-1-thread-4,5,main] Thread[pool-1-thread-3,5,main] Thread[pool-1-thread-2,5,main] notify()Thread[pool-1-thread-1,5,main] notifyAll()Thread[pool-1-thread-1,5,main] Thread[pool-1-thread-2,5,main] Thread[pool-1-thread-3,5,main] Thread[pool-1-thread-4,5,main] Thread[pool-1-thread-5,5,main] Timer canceled Task2.blocker.prodAll()Thread[pool-1-thread-6,5,main] Shutting downWaitingCall Interrupted Exception !!!WaitingCall Interrupted Exception !!!WaitingCall Interrupted Exception !!!WaitingCall Interrupted Exception !!!WaitingCall Interrupted Exception !!!WaitingCall Interrupted Exception !!!
上面这个例子说明
1.notify只会唤醒一个线程,而notifyAll会唤醒所有持当前锁的线程
2.Task.blocker.prod()或者Task.blocker.prodAll()并不会唤醒挂起的Task2线程
生产者和消费者
接下来这个例子是关于饭店,招待,厨师的例子,一家饭店拥有一个厨师,一个招待,招待在送菜的时候(meal!=null)厨师不能继续烧菜(即不能将null的meal重新创建对象)
package com.tij.thread.cooperate;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.TimeUnit;class Meal{ private final int orderNum; public Meal(int orderNum){ this.orderNum=orderNum; } @Override public String toString() { return "Meal-"+orderNum; }}class WaitPerson implements Runnable{ private Restaurant restaurant; public WaitPerson(Restaurant rc){ this.restaurant=rc; } @Override public void run() { try { while (!Thread.interrupted()) { synchronized (this) { while (restaurant.meal==null) { wait(); } } System.out.println("Waitperson got "+restaurant.meal); //synchronized (this) { synchronized (restaurant.chef) { restaurant.meal=null; //虽然在理论上使用notify()方法可以解决问题,但是在更复杂的任务中可能会有多个任务在特定对象锁上等待 //或者在团队协作中,有同事也使用了这个锁 restaurant.chef.notifyAll(); } } } catch (Exception e) { System.err.println("WaitPerson InterruptedException "); //e.printStackTrace(); } }}class Chef implements Runnable{ private Restaurant restaurant; private int count; public Chef(Restaurant rc){ this.restaurant=rc; } @Override public void run() { try { while (!Thread.interrupted()) { synchronized (this) { while (restaurant.meal!=null) { wait(); } } if (++count==10) { System.out.println("Out Of Food,Closing"); restaurant.exec.shutdownNow(); } System.out.println("Order Up!"); synchronized (restaurant.waitPerson) { restaurant.meal=new Meal(count); restaurant.waitPerson.notifyAll(); } TimeUnit.MILLISECONDS.sleep(100); } } catch (Exception e) { System.err.println("Chef InterruptedException "); //e.printStackTrace(); } }}public class Restaurant { Meal meal; ExecutorService exec=Executors.newCachedThreadPool(); WaitPerson waitPerson=new WaitPerson(this); Chef chef=new Chef(this); public Restaurant(){ exec.execute(chef); exec.execute(waitPerson); } public static void main(String[] args) { new Restaurant(); }}
1.需要再次重申的是wait()必须被包装在一个while()语句中,避免其它线程突然插足并改变条件
2.通常将run方法体放在try语句快中,在run方法体抛出异常后捕获并且有序的关闭
阅读全文
0 0
- java编程思想笔记-并发之线程协作(二)
- java编程思想笔记-并发之线程协作(一)
- java编程思想笔记-并发之线程协作(三)
- java编程思想笔记-并发之线程协作(四)
- Java编程思想 之 线程协作
- java编程思想笔记-并发之线程加入
- Java并发编程实战笔记(5)- 线程协作
- java编程思想笔记-并发之死锁
- java编程思想笔记-并发之CountDownLatch
- java编程思想笔记-并发之CyclicBarrier
- java编程思想笔记-并发之并发锁synchronized详解(二)
- Java并发之线程之间协作
- Java并发之线程间的协作
- (38)21.3.8 线程本地存储---Java编程思想之并发笔记
- java编程思想笔记-并发之并发锁(一)
- java编程思想笔记-并发之后台线程
- Java并发编程之线程(二)
- java编程思想-并发之线程异常处理器
- HDU 6106 Classes【水题】
- tf.train.exponential_decay的用法
- 为什么安装 jdk 时会有两个 jre ?
- 数据库连接池的理解
- OGNL概述
- java编程思想笔记-并发之线程协作(二)
- JAVA for和foreach 遍历的效率
- 为什么精英都是清单控(笔记)——社交清单
- 求高精度幂(南阳OJ155题)
- 1.A+B问题
- Python初步了解(六)
- windows下Idea使用git clone failed. Could not read from remote repository
- 8.10上课感悟
- 缺少DAO350.dll的解决方案