标签:生产 list ack block 数据 div notifyall tin bre
Guarded Suspension 设计模式可以保证,当线程在访问某个对象时,发现条件不满足,就挂起等待条件满足时再次访问
public class GuardedSuspensionQueue { // 定义存放Integer类型的queue private final LinkedList<String> queue = new LinkedList<String>(); // 定义queue的最大容量为5 private final int LIMIT = 5; public static final Random random = new Random(System.currentTimeMillis()); // 往queue中插入数据,如果queue中的元素超过了最大容量,则会陷入阻塞 public void offer(String data) { synchronized (this) { // 判断queue的当前元素是否超过了LIMIT while (queue.size() >= LIMIT) { // 挂起当前线程,使其陷入阻塞 System.out.println("向queue中添加元素,元素个数超过了限制,"+Thread.currentThread().getName()+"被挂起!"); try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } // 插入元素并且唤醒take线程 queue.addLast(data); this.notifyAll(); } } // 从队列中获取元素,如果队列此时为空,则会使当前线程阻塞 public String take() { synchronized (this) { // 判断如果队列为空 while (queue.isEmpty()) { // 则挂起当前线程 System.out.println(Thread.currentThread().getName()+"从queue中取出元素,元素个数为0,被挂起!"); try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); return null; } } //removeFirst不会返回null值,queue没有元素会抛出异常 String res = queue.removeFirst(); // 通知offer线程可以继续插入数据了 this.notifyAll(); return res; } } public static void main(String[] args) throws InterruptedException { GuardedSuspensionQueue queue = new GuardedSuspensionQueue(); TakerThread takerThread = new TakerThread(queue,"【线程A】"); takerThread.start(); Thread.sleep(2000); // 创建3个生产线程向queue中添加数据 IntStream.rangeClosed(1, 3).forEach(i -> { new Thread(() -> { for (int j = 1; j <= 5; j++) { queue.offer("【线程"+i+"】放入的"+j); } try { Thread.sleep(random.nextInt(1000)); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); }); Thread.sleep(10_000); takerThread.close(); } } class TakerThread extends Thread{ private volatile boolean close = false; private GuardedSuspensionQueue queue ; TakerThread(GuardedSuspensionQueue queue,String name){ this.queue = queue; setName(name); } @Override public void run() { while(!close) { String item = queue.take(); if(item == null) { break; } System.out.println(Thread.currentThread().getName() + "从queue中取出数据:" + item); try { Thread.sleep(GuardedSuspensionQueue.random.nextInt(1000)); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); break; } } } public void close() { this.close = close; this.interrupt(); } }
标签:生产 list ack block 数据 div notifyall tin bre
原文地址:https://www.cnblogs.com/moris5013/p/11778388.html