日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

多线程编程:阻塞、并发队列的使用总结

發布時間:2024/9/5 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 多线程编程:阻塞、并发队列的使用总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近,一直在跟設計的任務調度模塊周旋,目前終于完成了第一階段的調試。今天,我想借助博客園平臺把最近在設計過程中,使用隊列和集合的一些基礎知識給大家總結一下,方便大家以后直接copy。本文都是一些沒有技術含量的東西,只是做個總結,牛哥還請繞路。

老習慣,還是先跟各位紙上談會兒兵,首先說說隊列,他主要分為并發隊列和阻塞隊列,在多線程業務場景中使用最為普遍,我就主要結合我所做過的業務談談我對它們的看法,關于它們的API和官方解釋就不提了。

并發隊列

并發隊列:最常見的業務場景就是多個線程共享同一個隊列中的所有資源,就拿我們公司的業務場景來說,當用戶通過多個渠道下單后,然后就會有多個不同的客戶端通道同時去獲取訂單并處理訂單,為了加快訂單處理速度我們使用并發隊列來充當任務源頭,為了加快處理訂單速度,結合多線程并發來滿足需求。

并發隊列沒什么可說的,就是一個簡單的多線程編程操作,小Demo送給各位:

1 /** 2 * 并發隊列ConcurrentLinkedQueue的使用 3 */ 4 5 public class ConcurrentQueue { 6 7 public static void main(String[] args){ 8 ToyotaYQ yq = new ToyotaYQ(); 9 new Thread(yq,"ToyotaYQ_001").start(); 10 new Thread(yq,"ToyotaYQ_002").start(); 11 new Thread(yq,"ToyotaYQ_003").start(); 12 } 13 14 } 15 16 /** 17 * 任務來源 18 */ 19 class MQ{ 20 private static Queue<String> queue = null; //并發隊列(線程安全) 21 22 /** 23 * 初始化并發隊列 24 */ 25 public static Queue<String> initQueue(){ 26 if(queue == null){ 27 queue = new ConcurrentLinkedQueue<String>(); 28 } 29 String tasklist = "JF1GH78F18G036149,JF1SH95F6AG110830,JF1SJ94D7DG010387,JF1SH92F9CG269249,JF1SH92F5BG215090,JF1SH92F5BG222556,JF1SH92F4CG279994,JF1BR96D7CG114298,JF1BR96D0BG078632,JF1SH95F9AG094011,JF1SH98FXAG186997,JF1BM92D8BG022510,JF1BM92DXAG013855,JF1BM94D8EG036618"; 30 String[] split = tasklist.split(","); 31 List<String> task = Arrays.asList(split); //數組轉集合 32 queue.addAll(task); //按照集合中元素的順序將集合中全部元素放進隊列 33 34 return queue; 35 } 36 } 37 38 /** 39 * 制單客戶端 40 */ 41 class ToyotaYQ implements Runnable{ 42 43 private static final Object lock = new Object(); 44 private static Queue<String> queueYQ = MQ.initQueue(); 45 46 @Override 47 public void run() { 48 while(true){ 49 synchronized (lock){ //盡量減小鎖的粒度和范圍 50 String thisVIN = queueYQ.poll(); 51 if(thisVIN == null){ 52 break; 53 } 54 System.out.println(Thread.currentThread().getName() + "成功制單:" + thisVIN + "。剩余:" + queueYQ.size() + "個任務"); 55 } 56 } 57 } 58 } View Code

阻塞隊列

阻塞隊列:最常見的業務場景就是生產者不斷生產任務放進阻塞隊列中,消費者不斷從阻塞隊列中獲取任務;當阻塞隊列中填滿數據時,所有生產者端的線程自動阻塞,當阻塞隊列中數據為空時,所有消費端的線程自動阻塞。這些操作BlockingQueue都已經包辦了,不用我們程序員去操心了。

阻塞隊列我們常用的有:LinkedBlockingQueueArrayBlockingQueue,它們在各方面還是很大的區別的;ArrayBlockingQueue在put,take操作使用了同一個鎖,兩者操作不能同時進行,而LinkedBlockingQueue使用了不同的鎖,put操作和take操作可同時進行,以此來提高整個隊列的并發性能。

作為開發者,使用阻塞隊列需要注意的一點是:如果構造一個LinkedBlockingQueue對象,而沒有指定其容量大小,LinkedBlockingQueue會默認一個類似無限大小的容量(Integer.MAX_VALUE),這樣的話,如果生產者的速度一旦大于消費者的速度,也許還沒有等到隊列滿阻塞產生,系統內存就有可能已被消耗殆盡了。

阻塞隊列的一些常用方法

下面是我根據這幾天設計的任務調度功能模擬的一個小Demo,只不過項目中使用了MQ服務,這里用阻塞隊列完成可以代替:

1 public class BlockQueueDemo { 2 3 public static void main(String[] args){ 4 BlockingQueue<Integer> queue = new LinkedBlockingQueue<Integer>(2); //定長為2的阻塞隊列 5 //ExecutorService:真正的線程池接口 6 ExecutorService service = Executors.newCachedThreadPool(); //緩存線程池 7 //創建3個生產者: 8 ProducerDemo p1 = new ProducerDemo("車鑒定web端",queue); 9 ProducerDemo p2 = new ProducerDemo("車鑒定APP端",queue); 10 ProducerDemo p3 = new ProducerDemo("車鑒定接口端",queue); 11 ProducerDemo p4 = new ProducerDemo("車鑒定M棧",queue); 12 //創建三個消費者: 13 ConsumerDemo c1 = new ConsumerDemo("ToyotaYQ_001",queue); 14 ConsumerDemo c2 = new ConsumerDemo("ToyotaYQ_002",queue); 15 ConsumerDemo c3 = new ConsumerDemo("ToyotaYQ_003",queue); 16 17 //啟動線程 18 service.execute(p1); 19 service.execute(p2); 20 service.execute(p3); 21 service.execute(p4); 22 service.execute(c1); 23 service.execute(c2); 24 service.execute(c3); 25 26 } 27 } 28 29 /** 30 * 生產者 31 */ 32 class ProducerDemo implements Runnable { 33 private String producerName; 34 private BlockingQueue queue;//阻塞隊列 35 private Random r = new Random(); 36 37 //構造函數,傳入生產者名稱和操作的阻塞隊列 38 public ProducerDemo(String producerName,BlockingQueue queue) { 39 this.producerName = producerName; 40 this.queue = queue; 41 } 42 43 @Override 44 public void run() { 45 while(true){ 46 try { 47 int task = r.nextInt(100); //產生隨機數 48 System.out.println(producerName + "開始生產任務:" + task); 49 queue.put(task); //生產者向隊列中放入一個隨機數 50 Thread.sleep(5000); //減緩生產者生產的速度,如果隊列為空,消費者就會阻塞不會進行消費直到有數據被生產出來 51 } catch (InterruptedException e) { 52 e.printStackTrace(); 53 } 54 } 55 } 56 } 57 58 class ConsumerDemo implements Runnable{ 59 private String consumerName; 60 private BlockingQueue queue;//阻塞隊列 61 62 //構造函數,傳入消費者名稱和操作的阻塞隊列 63 public ConsumerDemo(String consumerName,BlockingQueue queue) { 64 this.consumerName = consumerName; 65 this.queue = queue; 66 } 67 68 @Override 69 public void run() { 70 while(true){ 71 try { 72 System.out.println(consumerName + "開始消費任務---" + queue.take());//消費者從阻塞隊列中消費一個隨機數 73 //Thread.sleep(500); 74 } catch (InterruptedException e) { 75 e.printStackTrace(); 76 } 77 } 78 } 79 }

?

開發中各位最常用最熟悉的不過也是集合了,但是前幾天在設計中突然想自己控制任務的分配和修改,這就需要用到靈活操作集合中的內容了,其它也沒什么,但是刪除集合中的元素這一點我們還是必須要很熟練的,雖然是需要借助迭代器來刪除的,但是還是記錄一下吧,方便以后copy。

刪除List集合中的某元素:

1 public class ListDemo { 2 3 public static void main(String[] args){ 4 ArrayList<String> arrList = new ArrayList<String>(); 5 String[] arr = {"一豐","廣豐","寶馬","奧迪","保時捷","沃爾沃","悍馬","路虎","凱迪拉克"}; 6 arrList.addAll(Arrays.asList(arr)); //將數組轉成集合 7 8 //刪除前: 9 for (String thisItem:arrList){ 10 System.out.println("---"+thisItem); 11 } 12 System.out.println("#########################"); 13 14 //使用迭代器刪除集合中的元素 15 Iterator it = arrList.iterator(); 16 while(it.hasNext()){ //it.hasNext()判斷是否還有下一個元素 17 if("悍馬".equals(it.next())){ //it.next()代表下一個元素 18 it.remove(); //【記得:remove()方法一定要調用迭代器的,不能調用List集合的】 19 } 20 } 21 22 //刪除后: 23 for (String thisItem:arrList){ 24 System.out.println("---"+thisItem); 25 } 26 27 } 28 }

?

轉載于:https://www.cnblogs.com/1315925303zxz/p/7809843.html

總結

以上是生活随笔為你收集整理的多线程编程:阻塞、并发队列的使用总结的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。