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();    }}
原创粉丝点击