java编程思想笔记-并发之线程协作(四)
来源:互联网 发布:淘宝网店登录 编辑:程序博客网 时间:2024/06/09 15:21
1.生产者,消费者队列
wait()和notifyAll()方法以每次交互握手的方式解决任务操作问题,concurrent类库使用BlockingQueue同步队列来解决任务的协作问题,同步队列在任何时刻只允许一个任务插入或者移除元素,这个接口有两个常用的实现LinkedBlockingQueue和ArrayBlockingQueue,前者是无界队列,后者具有固定的尺寸
如果消费者尝试获取空队列元素,那么这个队列可以挂起消费者,并在更多的元素可用时恢复消费者队列
示例
制作一个吐司需要烘干吐司,抹黄油,涂果酱三个步骤,利用BlockingQueue模拟吐司工厂生产吐司
class Toast{ public enum Status{ DRY,BUFFERED,JAMMED } private Status status=Status.DRY; private final int id; public Toast(int idn){ this.id=idn; } public void butter(){ status=Status.BUFFERED; } public void jam(){ status=Status.JAMMED; } public Status getStatus(){ return status; } public int getId(){ return id; } @Override public String toString() { return "Toast "+id+": "+status; }}class ToastQueue extends LinkedBlockingQueue<Toast>{}class Toaster implements Runnable{ private ToastQueue toastQueue; private int count=0; private Random rand=new Random(47); public Toaster (ToastQueue tq){ this.toastQueue=tq; } @Override public void run() { try { while (!Thread.interrupted()) { TimeUnit.MILLISECONDS.sleep(100+rand.nextInt(500)); Toast t=new Toast(count++); System.out.println(t); toastQueue.put(t); } } catch (Exception e) { System.out.println("ToasterInterruptException "); } System.out.println("Toaster off"); }}class Butter implements Runnable{ private ToastQueue dryQueue,butteredQueue; public Butter(ToastQueue dry,ToastQueue buttered) { dryQueue=dry; butteredQueue=buttered; } @Override public void run() { try { while (!Thread.interrupted()) { Toast t=dryQueue.take(); t.butter(); System.out.println(t); butteredQueue.put(t); } } catch (Exception e) { System.out.println("Butterer interrupted "); } System.out.println("Butterer off"); }}class Jammer implements Runnable{ private ToastQueue butteredQueue,finishedQueue; public Jammer(ToastQueue butteredQueue,ToastQueue finishedQueue){ this.butteredQueue=butteredQueue; this.finishedQueue=finishedQueue; } @Override public void run() { try { while (!Thread.interrupted()) { Toast t=butteredQueue.take(); t.jam(); System.out.println(t); finishedQueue.put(t); } } catch (Exception e) { System.out.println("Jammer Interrupted"); } System.out.println("Jammer Off"); }}class Eater implements Runnable{ private ToastQueue finishedQueue; private int counter; public Eater(ToastQueue finished){ this.finishedQueue=finished; } @Override public void run() { try { while (!Thread.interrupted()) { Toast t=finishedQueue.take(); if (t.getId()!=counter++||t.getStatus()!=Toast.Status.JAMMED) { System.err.println(">>>> Error:"+t); System.exit(1); }else { System.out.println("Chomp!"+t); } } } catch (Exception e) { System.out.println("Easter interrupted"); } System.out.println("Easter Off"); }}public class ToastOMatic { public static void main(String[] args) throws InterruptedException { ToastQueue dryQueue=new ToastQueue(), butteredQueue=new ToastQueue(), finishedQueue=new ToastQueue(); ExecutorService exec=Executors.newCachedThreadPool(); exec.execute(new Toaster(dryQueue)); exec.execute(new Butter(dryQueue, butteredQueue)); exec.execute(new Jammer(butteredQueue, finishedQueue)); exec.execute(new Eater(finishedQueue)); TimeUnit.SECONDS.sleep(5); exec.shutdownNow(); }}
从示例2可以看到,利用BlockingQueue避免了显示的使用wait,notify等方法
2.任务间使用管道输入输出
有时候需要利用输入输出在线程间通信,它们在Java输入输出类库中的对应物是PipedReader和PipedWriter,PipedReader是可中断的,interrupt()可以打断阻塞,而System.in.read()是不可中断的
示例:
利用PipedReader和PipedWriter打印26个大小写字母
class Sender implements Runnable{ private Random random=new Random(47); private PipedWriter out=new PipedWriter(); public PipedWriter getPipedWriter(){ return out; } @Override public void run() { try { while (true) { for (char c='A';c<='z';c++) { out.write(c); TimeUnit.MILLISECONDS.sleep(random.nextInt(500)); } } } catch (IOException e) { System.out.println("Sender-IOException"); } catch (InterruptedException e) { System.out.println("Sender-InterruptedException"); } }}class Receiver implements Runnable{ private PipedReader in; public Receiver(Sender sender) throws IOException{ in=new PipedReader(sender.getPipedWriter()); } @Override public void run() { try { while (true) { System.out.println("Read:"+(char)in.read()+","); } } catch (Exception e) { System.out.println("Receiver-IOException"); } }}public class PipedIO { public static void main(String[] args) throws Exception { Sender sender=new Sender(); Receiver receiver=new Receiver(sender); ExecutorService exec=Executors.newCachedThreadPool(); exec.execute(sender); exec.execute(receiver); TimeUnit.SECONDS.sleep(20); exec.shutdownNow(); }}
示例
利用BlockingQueue重写大小写字母示例
class Sender2 implements Runnable{ private Random random=new Random(47); BlockingQueue<Character>bq; public Sender2(BlockingQueue<Character>bq){ this.bq=bq; } @Override public void run() { try { while (true) { for (char c='A';c<='z';c++) { bq.add(c); TimeUnit.MILLISECONDS.sleep(random.nextInt(500)); } } } catch (InterruptedException e) { System.out.println("Sender2-InterruptedException"); } }}class Receiver2 implements Runnable{ BlockingQueue<Character>bq; public Receiver2(BlockingQueue<Character>bq){ this.bq=bq; } @Override public void run() { try { while (!Thread.interrupted()) { char c=bq.take(); System.out.println("receive:"+c); } } catch (InterruptedException e) { System.out.println("Receiver2-InterruptedException"); } }}public class PipedIOBlockingQueue { public static void main(String[] args) throws InterruptedException { ExecutorService exec=Executors.newCachedThreadPool(); BlockingQueue<Character>queue=new LinkedBlockingQueue<Character>(); exec.execute(new Sender2(queue)); exec.execute(new Receiver2(queue)); TimeUnit.SECONDS.sleep(5); exec.shutdownNow(); }}
阅读全文
0 0
- java编程思想笔记-并发之线程协作(四)
- java编程思想笔记-并发之线程协作(一)
- java编程思想笔记-并发之线程协作(二)
- java编程思想笔记-并发之线程协作(三)
- Java编程思想 之 线程协作
- java编程思想笔记-并发之线程加入
- Java 并发编程 四 协作
- Java并发编程实战笔记(5)- 线程协作
- java编程思想笔记-并发之死锁
- java编程思想笔记-并发之CountDownLatch
- java编程思想笔记-并发之CyclicBarrier
- Java并发之线程之间协作
- Java并发之线程间的协作
- (38)21.3.8 线程本地存储---Java编程思想之并发笔记
- java编程思想笔记-并发之并发锁(一)
- java编程思想笔记-并发之后台线程
- java编程思想-并发之线程异常处理器
- 并发(java编程思想)笔记
- Linux 下常用gdb的快捷键全
- topK的一种解决方法
- 各类排序以及折半查找
- B-树和B+树
- 部署后日志文件无法访问
- java编程思想笔记-并发之线程协作(四)
- 产品设计,应不应该追求高保真?
- webuploader 分片上传时 保存信息的java类
- ARM与X86 CPU架构对比区别
- PopupWindow+spinner使用方法
- Spring applicatoincontest.xml 配置
- spark2.2内核剖析---checkpoint与presist
- api url
- bzoj4917: Hash Killer IV