java_阻塞队列(FIFO先进先出)
ArrayBlockingQueue:由数组结构组成的有界阻塞队列;
LinkedBlockingQueue:由链表结构组成的有界阻塞队列(但大小默认值为:Integer.MAX_VALUE);
PriorityBlockingQueue:支持优先级排序的无界阻塞队列;
DelayQueue:使用优先级队列实现的延迟无界阻塞队列;
SynchronousQueue:不存储元素的阻塞队列,也即单个元素的队列;
LinkedTransferQueue:由链表结构组成的无界阻塞队列;
LinkedBlockingDeque:由链表结果组成的双向阻塞队列;
阻塞队列核心方法
add(e):为阻塞队列添加一个元素e,添加成功返回 true,当阻塞队列满时,抛出异常 java.lang.IllegalStateException: Queue full
remove():为阻塞队列移除一个元素,移除成功时返回移除的元素,当阻塞队列为空时,抛出异常 java.util.NoSuchElementException
element():检查当前阻塞队列的首个元素,成功时返回首个元素,当阻塞队列为空时,抛出异常 java.util.NoSuchElementException
offer(e):为阻塞队列添加一个元素e,添加成功返回 true,当阻塞队列满时返回 false
poll():为阻塞队列移除一个元素,移除成功时返回移除的元素,当阻塞队列为空时,返回 null
peek():检查当前阻塞队列的首个元素,成功时返回首个元素,当阻塞队列为空时,返回 null
put(e):为阻塞队列添加一个元素e,无返回值,当阻塞队列满时会阻塞线程,直到操作成功为止
take():为阻塞队列移除一个元素,成功时返回首个元素,当阻塞队列为空时会阻塞线程,直到操作成功为止
offer(e,time,unit):为阻塞队列添加一个元素e,添加成功返回 true,当阻塞队列满时会阻塞队列一段时间(time:long类型的时间,unit为时间单位),失败返回 false
poll(time,unit):为阻塞队列移除一个元素,移除成功时返回移除的元素,当阻塞队列为空时,会阻塞队列一段时间(time:long类型的时间,unit为时间单位),失败返回 null
SynchronousQueue:不存储元素的阻塞队列
import java.util.concurrent.BlockingQueue; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.TimeUnit; public class SynchronousQueueDemo { public static void main(String[] args) { BlockingQueue queue = new SynchronousQueue<>(); new Thread(() ->{ try { System.out.println(Thread.currentThread().getName()+"\t put 1"); queue.put(1); System.out.println(Thread.currentThread().getName()+"\t put 2"); queue.put(2); System.out.println(Thread.currentThread().getName()+"\t put 3"); queue.put(3); } catch (InterruptedException e) { e.printStackTrace(); } },"A").start(); new Thread(() ->{ try { try { TimeUnit.SECONDS.sleep(1); }catch (Exception e){ e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" 第一次移除队列元素"); queue.take(); try { TimeUnit.SECONDS.sleep(1); }catch (Exception e){ e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" 第二次移除队列元素"); queue.take(); try { TimeUnit.SECONDS.sleep(1); }catch (Exception e){ e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" 第三次移除队列元素"); queue.take(); } catch (InterruptedException e) { e.printStackTrace(); } },"B").start(); } }
生产者与消费者实例:(生产一个消费一个)
第一版(使用synchronized、wait 、 notify等方法进行实现)
第二版(使用ReentrantLock、await、signal / signalAll等方法进行进行实现)
第二版示例代码:
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; class ShareData {//资源类 private int number = 0; private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); public void increment() throws Exception { lock.lock(); try { //1、判断 while (number != 0) { //等待 condition.await(); } //2、干活 number++; System.out.println(Thread.currentThread().getName() + "\t" + number); //3、唤醒 condition.signalAll();//唤醒所有等待线程 } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void decrement() throws Exception { lock.lock(); try { //1、判断 while (number == 0) { //等待 condition.await(); } //2、干活 number--; System.out.println(Thread.currentThread().getName() + "\t" + number); //3、唤醒 condition.signalAll(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } } public class ProdConsumer_TraditionDemo { public static void main(String[] args) { ShareData shareData = new ShareData(); new Thread(() ->{ for (int i = 1; i <= 5; i++) { try { shareData.increment(); } catch (Exception e) { e.printStackTrace(); } } },"A").start(); new Thread(() ->{ for (int i = 1; i <= 5; i++) { try { shareData.decrement(); } catch (Exception e) { e.printStackTrace(); } } },"B").start(); } }
第三版:(volatile/CAS/AtomicInteger/BlockingQueue/线程交互/原子引用)等进行实现
第三版示例代码:
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; class MyResource{ private volatile boolean flag = true;//默认开启,进行生产+消费 volatile(可见性、不保证原子性、禁止指令重排) private AtomicInteger atomicInteger = new AtomicInteger();//原子整型类(保证原子性)、默认值:0 BlockingQueue<String> queue = null; public MyResource(BlockingQueue<String> queue) { this.queue = queue; System.out.println("当前传入的BlockingQueue:" + queue.getClass().getName()); } public void myProd()throws Exception{//生产蛋糕 String data = null; boolean retValue;//默认值为 false while (flag){ //atomicInteger.incrementAndGet();// ++atomicInteger //atomicInteger.getAndIncrement();// atomicInteger++ data = atomicInteger.incrementAndGet() + ""; retValue = queue.offer(data,2L, TimeUnit.SECONDS);//添加 data,若失败会阻塞2秒 返回false if (retValue){ System.out.println(Thread.currentThread().getName()+"\t 插入队列:"+data+" 成功"); }else { System.out.println(Thread.currentThread().getName()+"\t 插入队列:"+data+" 失败"); } TimeUnit.SECONDS.sleep(1);//每一秒生产 1个 } System.out.println(Thread.currentThread().getName()+"\t flag = false 生产结束"); } public void myConsumer()throws Exception{ String data = null; while (flag){ data = queue.poll(2L,TimeUnit.SECONDS);//获取 data,若失败会阻塞2秒 返回 null if (data == null || data.equalsIgnoreCase("")){ System.out.println(Thread.currentThread().getName()+"\t 2秒没有取到蛋糕 消费退出"); return; } System.out.println(Thread.currentThread().getName()+"\t 消费队列蛋糕:"+data+" 成功"); } } public void stop()throws Exception{ this.flag = false; } } /** * volatile/CAS/AtomicInteger/BlockingQueue/线程交互/原子引用 */ public class ProConsumer_BlockingQueueDemo { public static void main(String[] args) throws Exception { MyResource resource = new MyResource(new ArrayBlockingQueue<>(10)); new Thread(() ->{ try { resource.myProd(); } catch (Exception e) { e.printStackTrace(); } },"prod").start(); new Thread(() ->{ try { resource.myConsumer(); } catch (Exception e) { e.printStackTrace(); } },"consumer").start(); //睡眠5秒 try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(); System.out.println("5秒钟到,活动结束"); resource.stop(); } }