用Callable實現在走完10個執行緒之後再進行操作
昨天一個碰到了一個題目:
如何程式設計,使得主執行緒在跑完十個執行緒之後,再進行後續操作。
看到這個問題,我的第一反應就是可以使用Callable來實現。因為實現執行緒有兩種方式,實現Callable介面或者實現Runnable介面(至於繼承Thread類,我覺得這個方式其實本質上還是實現了Runnable介面)。但是用Runnable實現執行緒,我們一般是不知道執行緒有沒有跑完的,除非經過特殊處理(如使用CountDownLatch)(ps:使用執行緒池的submit()可以返回一個future,呼叫其isDone()方法也可以確認其是否完成,2018-05-08修改)。但是如果使用Callable實現執行緒,我們是可以在call()方法中返回一個值,來確認此執行緒跑完了。因此,我們可以在主執行緒中收集Callable的返回值,直到收集滿了十個以後,再進行後續操作,沒有收集滿的話,就讓主執行緒先休眠一會兒(這個只是初步想法,後續可以優化)。
現在,我們使用Callable來實現這個目的。
class MyCallable implements Callable<Integer>{ private static int count = 0; private static Random random = new Random(); private final int id = count ++; public Integer call() throws Exception { System.out.println("執行緒 \t" + id +"\t開始了"); //模擬工作耗時 int time = random.nextInt(3) + 1 ; System.out.println("執行緒 \t" + id +"\t耗時" + time + "秒"); Thread.sleep(1000 * time); return id; } }
/** * 2018-05-04 * @author liujie * */ public class TestCallable { public static void main(String[] args) throws Exception{ int SIZE = 10; int finished = 0; ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); //我們使用一個List來存放Callable的返回值 List<Future<Integer>> futures = new ArrayList<Future<Integer>>(); for (int i = 0; i < SIZE; i++) { Thread.sleep(100); futures.add(cachedThreadPool.submit(new MyCallable())); } while (finished < SIZE) { for (Future<Integer> future : futures) { Integer id = future.get(); System.out.println("主執行緒收集的到了 \t" + id + "\t執行緒的返回值"); finished ++ ; } } System.out.println(SIZE + "\t個執行緒都跑完了,繼續主執行緒的工作"); } }
如程式碼所示,我們在主執行緒中每隔0.1秒開啟一個執行緒,一共開啟十個,使用一個List收集callable的返回值,知道收集十個返回值為止。
控制檯列印情況如下:
執行緒 0 耗時1秒
執行緒 1 耗時1秒
執行緒 2 耗時3秒
執行緒 3 耗時1秒
執行緒 4 耗時1秒
執行緒 5 耗時3秒
執行緒 6 耗時3秒
執行緒 7 耗時2秒
執行緒 8 耗時1秒
執行緒 9 耗時3秒
主執行緒收集的到了 0 執行緒的返回值
主執行緒收集的到了 1 執行緒的返回值
主執行緒收集的到了 2 執行緒的返回值
主執行緒收集的到了 3 執行緒的返回值
主執行緒收集的到了 4 執行緒的返回值
主執行緒收集的到了 5 執行緒的返回值
主執行緒收集的到了 6 執行緒的返回值
主執行緒收集的到了 7 執行緒的返回值
主執行緒收集的到了 8 執行緒的返回值
主執行緒收集的到了 9 執行緒的返回值
10 個執行緒都跑完了,繼續主執行緒的工作
程式能夠正常完成題目的要求,即主執行緒會在十個執行緒都完成之後再進行後續工作但是,上面的程式碼其實忽略了一個重要的特性,那就是future.get()其實是阻塞的,也就是說當我們嘗試用get獲取返回值的時候,如果當時執行緒還沒有跑完,這時候其實主執行緒就會一直等在這裡,直到該執行緒跑完並返回一個值。
因此,以上程式碼可以優化成如下所示:
public class TestCallable {
public static void main(String[] args) throws Exception{
int SIZE = 10;
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
//我們使用一個List來存放Callable的返回值
List<Future<Integer>> futures = new ArrayList<Future<Integer>>();
for (int i = 0; i < SIZE; i++) {
Thread.sleep(100);
futures.add(cachedThreadPool.submit(new MyCallable()));
}
for (Future<Integer> future : futures) {
Integer id = future.get();
System.out.println("主執行緒收集的到了 \t" + id + "\t執行緒的返回值");
}
System.out.println(SIZE + "\t個執行緒都跑完了,繼續主執行緒的工作");
}
}
控制檯的情況也跟上面的一樣。
還有一點值得注意的是,
主執行緒收集的到了 0 執行緒的返回值
主執行緒收集的到了 1 執行緒的返回值
主執行緒收集的到了 2 執行緒的返回值
主執行緒收集的到了 3 執行緒的返回值
主執行緒收集的到了 4 執行緒的返回值
主執行緒收集的到了 5 執行緒的返回值
主執行緒收集的到了 6 執行緒的返回值
主執行緒收集的到了 7 執行緒的返回值
主執行緒收集的到了 8 執行緒的返回值
主執行緒收集的到了 9 執行緒的返回值
其實執行緒9有可能比執行緒0先跑完,但是由於我們在建立Future的List的時候,是按照從0開始的,在future.get()獲取返回值的時候,也是先從0開始。
其實執行緒9有可能比執行緒0先跑完,但是由於我們在建立Future的List的時候,是按照從0開始的,在future.get()獲取返回值的時候,也是先從0開始。
其實要完成題目的要求,更好地是使用CountDownLatch來完成,後續我將會補上用CountDownLatch來完成的部落格。
相關推薦
用Callable實現在走完10個執行緒之後再進行操作
昨天一個碰到了一個題目:如何程式設計,使得主執行緒在跑完十個執行緒之後,再進行後續操作。看到這個問題,我的第一反應就是可以使用Callable來實現。因為實現執行緒有兩種方式,實現Callable介面或者實現Runnable介面(至於繼承Thread類,我覺得這個方式其實本質
java實現【有三個執行緒ID分別是A、B、C,請有多線程式設計實現,在螢幕上迴圈列印10次ABC.】
該題應屬於生產者消費者模式一類 生產者消費者模式:根據標誌位來發訊息,實現對執行緒的控制。 直接貼答案了,請各位大蝦們指正哦。 建立三個執行緒 如下:ThreadA、ThreadB、ThreadC public class ThreadA implements Ru
JAVA多執行緒10個執行緒處理1000個數據
import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import j
讓10個執行緒按順序打印出0123456789
思路 1、通過公正瑣object對10個執行緒進行管理,喚醒所有執行緒或者阻塞等待。 2、通過orderNum通知下一個執行緒需要輸出的數字 程式碼 public class Printer { private static final
Linux平臺用C++實現訊號量,同步執行緒
使用Linux平臺上現有的訊號量sem_t相關的一組API,可以方便地進行執行緒同步。現在用pthread_mutex_t和pthread_cond_t相關的一組API實現訊號量機制。這組API包括:pthread_mutex_init,pthread_cond_init,pthread_mu
編寫10個執行緒,第一個執行緒從1加到10...
11、編寫10個執行緒,第一個執行緒從1加到10,第二個執行緒從11加到20...第十個執行緒從91加到100,最後再把十個執行緒結果相加。public class Accumulator exten
Callable實現帶有返回值的執行緒
我們都知道執行緒是沒有返回值的,在Runnable介面中,只有一個抽象的Run方法,使用Callable我們能夠實現帶有返回值得的執行緒,下面是一個demo /** * */ package com.mingrisoft.threadone; impo
筆記:Java實現三個執行緒A B C,BC執行緒執行完再執行A線
final Lock lc = new ReentrantLock(); .. run() { lc.lock(); ... lc.unlock(); } 可能開啟方式不對吧,沒實現! 改用join() 可以實現(BC與A以單執行緒模式執行),程式碼如下: package
Java多執行緒--三個執行緒分別列印a,b,c.請用多執行緒實現迴圈列印15次abc
掃盲: 想想自己多執行緒解決生產消費者問題就知道個synchronized,真是慚愧 為做此題目特意學習新的多執行緒知識–ReentrantLock跟synchronized一樣都是Java中的可重入鎖(可以在內部鎖中拿到外部鎖) Con
一個關於執行緒的經典面試題,要求用三個執行緒,按順序列印1,2,3,4,5.... 71,72,73,74, 75. 執行緒1先列印1,2,3,4,5, * 然後是執行緒2列印6,7,8,9,10, 然後是
package thread; /** * * 一個關於執行緒的經典面試題,要求用三個執行緒,按順序列印1,2,3,4,5.... 71,72,73,74, 75. 執行緒1先列印1,2,3,4,5, * 然後是執行緒2列印6,7,8,9,10, 然後是執行緒3列印
用js實現隨機選取10–100之間的10個數字,存入一個數組,並排序
方法一: <!DOCTYPE html> <html><head><meta charset="utf-8"><title>好好學習天天向上</title><script type="text/j
用訊號量(互斥鎖)實現兩個執行緒交替列印
本文實現兩個執行緒交替列印,採用的是逐步新增程式碼,分析每一步程式碼的作用,若想要看最終版本可直接翻看後面的最終版本。(本文以訊號量為例,互斥鎖的實現只需將訊號量的函式換成相應的互斥鎖的函式,互斥鎖(訊號量)函式不知道的看https://blog.csdn.net/liqia
ConcurrentHashMap原理(2)之用分離鎖實現多個執行緒間的併發寫操作
ConcurrentHashMap 類 ConcurrentHashMap 在預設併發級別會建立包含 16 個 Segment 物件的陣列。每個 Segment 的成員物件 table 包含若干個散列表的桶。每個桶是由 HashEntry 連結起來的一個連結串列。如果鍵能均
教育,創新,提升:Indiegogo和Kickstarter上受中國用戶支持的10個眾籌項目
即將 school -c 藝術家 new 技術分享 www ouya 積極 中國的經濟正在迅速發展,已成為世界第二大經濟體。中國家庭隨著經濟水平的提高,越來越多父母願意將自己的子女送到海外留學。 家長們希望自己的子女可以有機會接受國外大學優質的教育, 以便他們將來可以學成歸
究極難題 :一個執行10秒以上至無窮的呼叫函式,成功後有返回值。在多工執行緒中怎麼實現呼叫不卡住該執行緒?
究極難題 :一個執行10秒以上至無窮的呼叫函式,成功後有返回值。在多工執行緒中怎麼實現呼叫不卡住該執行緒? Note:一旦呼叫函式,中途無法取消。 思路一:讓其執行在獨立執行緒內。加超時時間。 1. 在超時時間內函式有返回值,則函式執行結束。則獨立執行緒結束。 2. 在超時時
用面向物件重寫thread 實現多次呼叫一個執行緒
思路: 利用thread類中,run方法在子執行緒中呼叫,其他方法在主執行緒呼叫,所以將生產者寫入主執行緒,將消費者寫入run函式中在子執行緒中執行,完成生產者消費者模型 注意: 1. 要在 init 函式中例項化一個Queue佇列作為生產者消費者中介 2. 要在 init 函式中把d
Java-執行緒(十個執行緒實現1~100求和)
這道題我大概搞了兩個小時左右吧。 可是我發現總是不對,最後發現我做不出來了,因為我並未真正搞清整個程式的執行,以及對那些關鍵詞(我指的是synchronized、wait()、notify()等這些玩意兒)的理解和使用都不清楚,更別說寫出來整個程式了。 public class Fort
java實現多個執行緒達到一個闕伐值後一起執行
給大家推薦個靠譜的公眾號程式設計師探索之路,大家一起加油 1. CountDownLatch 1.1 簡介 CountDownLatch是一個同步輔助類,通過它可以完成類似於阻塞當前執行緒的功能,即:一個執行緒或多個執行緒一直等待,直到其他執行緒執行的操作完成。CountDownLatch用
多執行緒同步之——兩個執行緒序列順序列印奇數和偶數的兩種實現
題目:一道經典的執行緒併發的問題,執行緒a列印1、3、5……,執行緒b列印2、4、6……,兩個執行緒交替執行輸出1、2、3、4、5、6…… 要點: package com.test; import java.util.concurrent.locks.
現在有T1、T2、T3三個執行緒,你怎樣保證T2在T1執行完後執行,T3在T2執行完後執行
這是個基礎的執行緒問題,主要是考核join方法的。不瞭解這個方法的話會感覺很懵逼。 假設現在有兩個執行緒A、B。如果在A的run方法中呼叫B.join(),表示A需要在B執行緒上面等待,也就是需要在B執行緒執行完成之後才能再次執行。瞭解這個概念之後,這個問題就很簡單了,java程式碼如下: