import java.util.Random; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.IntStream; public class Test { public static void main(String[] args){ ProductionChannelTest.test(); } } abstract class InstructionBook{ public final void create(){ this.firstProcess(); this.sedoncProcess(); } protected abstract void firstProcess(); protected abstract void sedoncProcess(); } class Production extends InstructionBook{ private final int prodID; public Production(int prodID) { this.prodID = prodID; } @Override protected void firstProcess() { System.out.println("execute the "+prodID+" first process"); } @Override protected void sedoncProcess() { System.out.println("execute the "+prodID+" second process"); } } class Worker extends Thread{ private final ProductionChannel channel; private final static Random random = new Random(System.currentTimeMillis()); public Worker(String name, ProductionChannel channel) { super(name); this.channel = channel; } @Override public void run() { while (true) { try{ Production production = channel.takeProduction(); System.out.println(getName()+" process the "+production); production.create(); TimeUnit.SECONDS.sleep(random.nextInt(10)); } catch (InterruptedException e) { e.printStackTrace(); } } } } class ProductionChannel{ private final static int MAX_PROD = 100; private final Production[] productionQueue; private int tail; //队列尾 private int head; //队列头 private int total; //当前流水有多少个待加工的产品 private final Worker[] workers; public ProductionChannel(int workSize) { this.workers=new Worker[workSize]; this.productionQueue=new Production[MAX_PROD]; for (int i = 0; i < workSize; i++) { workers[i]=new Worker("Worker-"+i,this); workers[i].start(); } } public void offerProduction(Production production){ synchronized (this) { while (total >= productionQueue.length) { try{ this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } productionQueue[tail]=production; tail=(tail+1)%productionQueue.length; total++; this.notifyAll(); } } public Production takeProduction(){ synchronized (this) { while (total <= 0) { try{ this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } Production production = productionQueue[head]; head = (head+1)%productionQueue.length; total--; this.notifyAll();; return production; } } class ProductionChannelTest{ public static void test(){ final ProductionChannel channel = new ProductionChannel(5); AtomicInteger productionNo = new AtomicInteger(); IntStream.range(1,8).forEach(i->new Thread(()->{ while(true){ channel.offerProduction(new Production(productionNo.getAndIncrement())); try{ TimeUnit.SECONDS.sleep(ThreadLocalRandom.current().nextInt(10)); } catch (InterruptedException e) { e.printStackTrace(); } } }).start()); } }