Java-Queue总结
1. ConcurrentLinkedQueue
基础链表同步队列。
import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; //底层链表实现 队列,先进先出 public class Test_03_ConcurrentLinkedQueue { public static void main(String[] args) { Queue<String> queue = new ConcurrentLinkedQueue<>(); for (int i = 0; i < 10; i++) { queue.offer("value" + i); } System.out.println(queue); System.out.println(queue.size()); //peek() 查看queue中的首数据 System.out.println(queue.peek()); System.out.println(queue.size()); //poll()->获取queue首数据 System.out.println(queue.poll()); System.out.println(queue.size()); } }
LinkedBlockingQueue
阻塞队列,队列容量不足自动阻塞,队列容量为 0 自动阻塞
import java.util.Random; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; /** 并发容器 - LinkedBlockingQueue * 阻塞容器。 * put & take - 自动阻塞。 * put自动阻塞, 队列容量满后,自动阻塞 * take自动阻塞方法, 队列容量为0后,自动阻塞。 */ public class Test_04_LinkBlockingQueue { final BlockingQueue<String> queue = new LinkedBlockingQueue<>(); final Random r = new Random(); public static void main(String[] args) { final Test_04_LinkBlockingQueue t = new Test_04_LinkBlockingQueue(); new Thread(new Runnable() { @Override public void run() { while(true){ try { t.queue.put("value"+t.r.nextInt(1000)); TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } } }, "producer").start(); for(int i = 0; i < 3; i++){ new Thread(new Runnable() { @Override public void run() { while(true){ try { System.out.println(Thread.currentThread().getName() + " - " + t.queue.take()); } catch (InterruptedException e) { e.printStackTrace(); } } } }, "consumer"+i).start(); } } }
ArrayBlockingQueue
底层数组实现的有界队列。自动阻塞。根据调用 API(add/put/offer)不同,有不同特 性。 当容量不足的时候,有阻塞能力。 add 方法在容量不足的时候,抛出异常。 put 方法在容量不足的时候,阻塞等待。 offer 方法, 单参数 offer 方法,不阻塞。容量不足的时候,返回 false。当前新增数据操作放弃。 三参数 offer 方法(offer(value,times,timeunit)),容量不足的时候,阻塞 times 时长(单 位为 timeunit),如果在阻塞时长内,有容量空闲,新增数据返回 true。如果阻塞时长范围 内,无容量空闲,放弃新增数据,返回 false
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.TimeUnit; public class Test_05_ArrayBlockingQueue { //当容量不足的时候,有阻塞能力 //add 方法在容量不足的时候,抛出异常 //put 方法在容量不如的时候,阻塞等待 //offer 方法,单参数,容量不足的时候,返回false。当前新增数据操作放弃 //offer 三参数,容量不足的时候,阻塞times时长(单位为timeunit),如果在阻塞时长内, //有容量空闲,新增数据返回true,如果阻塞时长范围内,无容量空闲,放弃新增数据,返回false final BlockingQueue<String> queue = new ArrayBlockingQueue<>(3); public static void main(String[] args) { final Test_05_ArrayBlockingQueue t = new Test_05_ArrayBlockingQueue(); for (int i = 0; i < 5; i++) { // System.out.println("add method : " + t.queue.add("value"+i)); /* * try { t.queue.put("put"+i); } catch (InterruptedException e) { * e.printStackTrace(); } System.out.println("put method : " + i); */ // System.out.println("offer method : " + t.queue.offer("value"+i)); try { System.out.println("offer method : " + t.queue.offer("value" + i, 1, TimeUnit.SECONDS)); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(t.queue); } }
DelayQueue
延时队列。根据比较机制,实现自定义处理顺序的队列。常用于定时任务。 如:定时关机
import java.util.concurrent.BlockingQueue; import java.util.concurrent.DelayQueue; import java.util.concurrent.Delayed; import java.util.concurrent.TimeUnit; //有顺序有时间的排序 //延时队列,根据比较机制,实现自定义处理顺序的队列。常用于定时任务 public class Test_06_DelayQueue { static BlockingQueue<MyTask_06> queue = new DelayQueue<>(); public static void main(String[] args) throws InterruptedException { long value = System.currentTimeMillis(); MyTask_06 task1 = new MyTask_06(value + 2000); MyTask_06 task2 = new MyTask_06(value + 1000); MyTask_06 task3 = new MyTask_06(value + 3000); MyTask_06 task4 = new MyTask_06(value + 2500); MyTask_06 task5 = new MyTask_06(value + 1500); queue.put(task1); queue.put(task2); queue.put(task3); queue.put(task4); queue.put(task5); System.out.println(queue); System.out.println(value); for (int i = 0; i < 5; i++) { System.out.println(queue.take()); } } } class MyTask_06 implements Delayed { private long compareValue; public MyTask_06(long compareValue) { this.compareValue = compareValue; } /** * 比较大小。自动实现升序 建议和getDelay方法配合完成。 * 如果在DelayQueue是需要按时间完成的计划任务,必须配合getDelay方法完成。 */ @Override public int compareTo(Delayed o) { return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS)); } /** * 获取计划时长的方法。 根据参数TimeUnit来决定,如何返回结果值。 */ @Override public long getDelay(TimeUnit unit) { return unit.convert(compareValue - System.currentTimeMillis(), TimeUnit.MILLISECONDS); } @Override public String toString() { return "Task compare value is : " + this.compareValue; } }
LinkedTransferQueue
转移队列,使用 transfer 方法,实现数据的即时处理。没有消费者,就阻塞
/** * 并发容器 - LinkedTransferQueue * 转移队列 * add - 队列会保存数据,不做阻塞等待。 * transfer - 是TransferQueue的特有方法。必须有消费者(take()方法的调用者)。 * 如果没有任意线程消费数据,transfer方法阻塞。一般用于处理即时消息。 */ import java.util.concurrent.LinkedTransferQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.TransferQueue; public class Test_07_TransferQueue { TransferQueue<String> queue = new LinkedTransferQueue<>(); public static void main(String[] args) { final Test_07_TransferQueue t = new Test_07_TransferQueue(); /* * new Thread(new Runnable() { * * @Override public void run() { try { * System.out.println(Thread.currentThread().getName() + * " thread begin " ); * System.out.println(Thread.currentThread().getName() + " - " + * t.queue.take()); } catch (InterruptedException e) { * e.printStackTrace(); } } }, "output thread").start(); * * try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { * e.printStackTrace(); } * * try { t.queue.transfer("test string"); } catch (InterruptedException * e) { e.printStackTrace(); } */ new Thread(new Runnable() { @Override public void run() { try { t.queue.transfer("test string"); // t.queue.add("test string"); System.out.println("add ok"); } catch (Exception e) { e.printStackTrace(); } } }).start(); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } new Thread(new Runnable() { @Override public void run() { try { System.out.println(Thread.currentThread().getName() + " thread begin "); System.out.println(Thread.currentThread().getName() + " - " + t.queue.take()); } catch (InterruptedException e) { e.printStackTrace(); } } }, "output thread").start(); } }
SynchronusQueue
同步队列,是一个容量为 0 的队列。是一个特殊的 TransferQueue。 必须现有消费线程等待,才能使用的队列。 add 方法,无阻塞。若没有消费线程阻塞等待数据,则抛出异常。 put 方法,有阻塞。若没有消费线程阻塞等待数据,则阻塞
import java.util.concurrent.BlockingQueue; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.TimeUnit; public class Test_08_SynchronusQueue { BlockingQueue<String> queue = new SynchronousQueue<>(); public static void main(String[] args) { final Test_08_SynchronusQueue t = new Test_08_SynchronusQueue(); new Thread(new Runnable() { @Override public void run() { try { System.out.println(Thread.currentThread().getName() + " thread begin " ); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " - " + t.queue.take()); } catch (InterruptedException e) { e.printStackTrace(); } } }, "output thread").start(); /*try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }*/ // t.queue.add("test add"); try { t.queue.put("test put"); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " queue size : " + t.queue.size()); } }