在Java多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列(先进先出)。Java提供的线程安全的Queue可以分为阻塞队列和非阻塞队列,其中阻塞队列的典型例子是BlockingQueue,非阻塞队列的典型例子是ConcurrentLinkedQueue,在实际应用中要根据实际需要选用阻塞队列或者非阻塞队列。
注:什么叫线程安全?这个首先要明确。线程安全就是说多线程访问同一代码,不会产生不确定的结果。
并行和并发区别
1、并行是指两者同时执行一件事,比如赛跑,两个人都在不停的往前跑;
2、并发是指资源有限的情况下,两者交替轮流使用资源,比如一段路(单核CPU资源)同时只能过一个人,A走一段后,让给B,B用完继续给A ,交替使用,目的是提高效率
LinkedBlockingQueue
由于LinkedBlockingQueue实现是线程安全的,实现了先进先出等特性,是作为生产者消费者的首选,LinkedBlockingQueue
可以指定容量,也可以不指定,不指定的话,默认最大是Integer.MAX_VALUE,其中主要用到put和take方法,put方法在队列满的时候会阻塞直到有队列成员被消费,take方法在队列空的时候会阻塞,直到有队列成员被放进来。
1 package cn.thread; 2 3 import java.util.concurrent.BlockingQueue; 4 import java.util.concurrent.ExecutorService; 5 import java.util.concurrent.Executors; 6 import java.util.concurrent.LinkedBlockingQueue; 7 8 /** 9 * 多线程模拟实现生产者/消费者模型 10 */ 11 public class BlockingQueueTest2 { 12 /** 13 * 14 * 定义装苹果的篮子 15 * 16 */ 17 public class Basket { 18 // 篮子,能够容纳3个苹果 19 BlockingQueue<String> basket = new LinkedBlockingQueue<String>(3); 20 21 // 生产苹果,放入篮子 22 public void produce() throws InterruptedException { 23 // put方法放入一个苹果,若basket满了,等到basket有位置 24 basket.put("An apple"); 25 } 26 27 // 消费苹果,从篮子中取走 28 public String consume() throws InterruptedException { 29 // take方法取出一个苹果,若basket为空,等到basket有苹果为止(获取并移除此队列的头部) 30 return basket.take(); 31 } 32 } 33 34 // 定义苹果生产者 35 class Producer implements Runnable { 36 private String instance; 37 private Basket basket; 38 39 public Producer(String instance, Basket basket) { 40 this.instance = instance; 41 this.basket = basket; 42 } 43 44 public void run() { 45 try { 46 while (true) { 47 // 生产苹果 48 System.out.println("生产者准备生产苹果:" + instance); 49 basket.produce(); 50 System.out.println("!生产者生产苹果完毕:" + instance); 51 // 休眠300ms 52 Thread.sleep(300); 53 } 54 } catch (InterruptedException ex) { 55 System.out.println("Producer Interrupted"); 56 } 57 } 58 } 59 60 // 定义苹果消费者 61 class Consumer implements Runnable { 62 private String instance; 63 private Basket basket; 64 65 public Consumer(String instance, Basket basket) { 66 this.instance = instance; 67 this.basket = basket; 68 } 69 70 public void run() { 71 try { 72 while (true) { 73 // 消费苹果 74 System.out.println("消费者准备消费苹果:" + instance); 75 System.out.println(basket.consume()); 76 System.out.println("!消费者消费苹果完毕:" + instance); 77 // 休眠1000ms 78 Thread.sleep(1000); 79 } 80 } catch (InterruptedException ex) { 81 System.out.println("Consumer Interrupted"); 82 } 83 } 84 } 85 86 public static void main(String[] args) { 87 BlockingQueueTest2 test = new BlockingQueueTest2(); 88 89 // 建立一个装苹果的篮子 90 Basket basket = test.new Basket(); 91 92 ExecutorService service = Executors.newCachedThreadPool(); 93 Producer producer = test.new Producer("生产者001", basket); 94 Producer producer2 = test.new Producer("生产者002", basket); 95 Consumer consumer = test.new Consumer("消费者001", basket); 96 service.submit(producer); 97 service.submit(producer2); 98 service.submit(consumer); 99 // 程序运行5s后,所有任务停止 100 // try { 101 // Thread.sleep(1000 * 5); 102 // } catch (InterruptedException e) { 103 // e.printStackTrace(); 104 // } 105 // service.shutdownNow(); 106 } 107 108 }