/**
使用“生产者-消费者模式”编写代码实现:线程A随机间隔(10~200ms)按顺序生成1到100的数字(共100个),
放到某个队列中.3个线程B、C、D即时消费这些数据,线程B打印(向控制台)所有被2整除的数,
线程C打印被3整除的数,线程D打印其它数据,要求数字的打印是有序的(从1到100)
限时40分钟,可以使用IDE及第三方类库
**/
先说一下阿里大牛的评价:我下面写的程序有个问题,如果B线程挂起了,C,D线程运行的话,有可能顺序会不一致。当然不能用三个queue,让B,C,D分别消费,因为太简单了。
应该这样,每次取出一个数来,使用wait(),notify(),先让B运行,然后C运行,然后D运行;就能保证顺序了,下面是我写的程序,暂时没有时间修改,以后有时间了,会进行修改:
package com.sankuai.qcs.regulation.TestCase; import lombok.Data; @Data public class aliObj implements Comparable<aliObj> { private final int intData; public boolean BisDone; public boolean CisDone; public aliObj(int d){ intData = d; BisDone=false; CisDone=false; } public int getData(){ return intData; } @Override public String toString(){ return "data:"+intData; } @Override public int compareTo(aliObj o) { if(this.intData>o.intData) { return 1; } else if(this.intData<o.intData) { return -1; } else { return 0; } } }
package com.sankuai.qcs.regulation.TestCase; import java.util.Comparator; import java.util.Random; import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.TimeUnit; public class Producer implements Runnable { private volatile boolean isRunning = true; int capacity = 100; PriorityBlockingQueue<aliObj> queue = new PriorityBlockingQueue(capacity, new Comparator<aliObj>() { @Override public int compare(aliObj i1, aliObj i2) { return i2.getIntData() - i1.getIntData(); } }); public Producer(PriorityBlockingQueue<aliObj> queue){ this.queue = queue; } @Override public void run() { if (isRunning) { Random r = new Random(); System.out.println("start producting id:" + Thread.currentThread().getId()); try { for (int i = 0; i < 100; i++) { Thread.sleep(10 + r.nextInt(190)); //停顿 10~200毫秒 System.out.println(i+1 + " 加入队列"); if (!queue.offer(new aliObj(i + 1), 2, TimeUnit.SECONDS)) { System.err.println(i+1+" 加入队列失败"); } } } catch (InterruptedException e) { e.printStackTrace(); Thread.currentThread().interrupt(); } } } public void stop() { isRunning = false; } }
package com.sankuai.qcs.regulation.TestCase; import java.util.concurrent.PriorityBlockingQueue; public class ConsumerB implements Runnable{ private PriorityBlockingQueue<aliObj> queue; public ConsumerB(PriorityBlockingQueue<aliObj> queue){ this.queue = queue; } @Override public void run() { System.out.println("start ConsumerB id :"+Thread.currentThread().getId()); try{ while(true){ aliObj data = queue.take(); if(data != null) { if(data.isBisDone()==false && data.getData()%2==0) { System.out.println("可以被2整除的数:"+data); data.setBisDone(true); if(data.getData()%3==0) queue.offer(data); } else{ queue.offer(data); } } } }catch (InterruptedException e) { e.printStackTrace(); Thread.currentThread().interrupt(); } } }
package com.sankuai.qcs.regulation.TestCase; import java.util.concurrent.PriorityBlockingQueue; public class ConsumerC implements Runnable{ private PriorityBlockingQueue<aliObj> queue; public ConsumerC(PriorityBlockingQueue<aliObj> queue){ this.queue = queue; } @Override public void run() { System.out.println("start ConsumerC id :"+Thread.currentThread().getId()); try{ while(true){ aliObj data = queue.take(); if(data != null) { if (data.isCisDone()==false && data.getData() % 3 == 0) { System.out.println("可以被3整除的数:" + data); if(data.getData()%2==0) { data.setCisDone(true); queue.offer(data); } } else { queue.offer(data); } } } }catch (InterruptedException e) { e.printStackTrace(); Thread.currentThread().interrupt(); } } }
package com.sankuai.qcs.regulation.TestCase; import java.util.concurrent.PriorityBlockingQueue; public class ConsumerD implements Runnable{ private PriorityBlockingQueue<aliObj> queue; public ConsumerD(PriorityBlockingQueue<aliObj> queue){ this.queue = queue; } @Override public void run() { System.out.println("start ConsumerD id :"+Thread.currentThread().getId()); try{ while(true){ aliObj data = queue.take(); if(data != null) { if((data.getData()%2!=0)&&(data.getData()%3!=0)) { System.out.println("既不可以被2整除,也不可以被3整除的数:"+data); } } } }catch (InterruptedException e) { e.printStackTrace(); Thread.currentThread().interrupt(); } } }
package com.sankuai.qcs.regulation.TestCase; import java.util.concurrent.*; public class Main { public static void main(String[] args) throws InterruptedException { PriorityBlockingQueue<aliObj> queue = new PriorityBlockingQueue<>(); Producer p1 = new Producer(queue); ConsumerB b1 = new ConsumerB(queue); ConsumerC c1 = new ConsumerC(queue); ConsumerD d1 = new ConsumerD(queue); ExecutorService service = Executors.newCachedThreadPool(); service.execute(p1); service.execute(b1); service.execute(c1); service.execute(d1); p1.stop(); Thread.sleep(3000); service.shutdown(); } }