国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

Java多線程--讓主線程等待所有子線程執行完畢在執行

2019-11-26 13:35:29
字體:
來源:轉載
供稿:網友

朋友讓我幫忙寫個程序從文本文檔中導入數據到oracle數據庫中,技術上沒有什么難度,文檔的格式都是固定的只要對應數據庫中的字段解析就行了,關鍵在于性能。

數據量很大百萬條記錄,因此考慮到要用多線程并發執行,在寫的過程中又遇到問題,我想統計所有子進程執行完畢總共的耗時,在第一個子進程創建前記錄當前時間用System.currentTimeMillis()在最后一個子進程結束后記錄當前時間,兩次一減得到的時間差即為總共的用時,代碼如下 

long tStart = System.currentTimeMillis(); System.out.println(Thread.currentThread().getName() + "開始");//打印開始標記 for (int ii = 0; ii < threadNum; ii++) {//開threadNum個線程 Runnable r = new Runnable(){ @Override public void run(){ System.out.println(Thread.currentThread().getName() + "開始"); //做一些事情... ... System.out.println(Thread.currentThread().getName() + "結束."); } } Thread t = new Thread(r); t.start(); } System.out.println(Thread.currentThread().getName() + "結束.");//打印結束標記 long tEnd = System.currentTimeMillis(); System.out.println("總共用時:"+ (tEnd - tStart) + "millions"); 

結果是幾乎在for循環結束的瞬間就執行了主線程打印總共用時的語句,原因是所有的子線程是并發執行的,它們運行時主線程也在運行,這就引出了一個問題即本文標題如何"讓主線程等待所有子線程執行完畢"。試過在每個子線程開始后加上t.join(),結果是所有線程都順序執行,這就失去了并發的意義了,顯然不是我想要的。 

網上Google了很久也沒有找到解決方案,難道就沒有人遇到過這種需求嗎?還是這個問題太簡單了?無耐只得自己想辦法了... 

最后我的解決辦法是,自定義一個ImportThread類繼承自java.lang.Thread,重載run()方法,用一個List屬性保存所有產生的線程,這樣只要判斷這個List是否為空就知道還有沒有子線程沒有執行完了,類代碼如下: 

public class ImportThread extends Thread { private static List<Thread> runningThreads = new ArrayList<Thread>(); public ImportThread() { } @Override public void run() { regist(this);//線程開始時注冊 System.out.println(Thread.currentThread().getName() + "開始...");//打印開始標記 //做一些事情... ... unRegist(this);//線程結束時取消注冊 System.out.println(Thread.currentThread().getName() + "結束.");//打印結束標記 } public void regist(Thread t){   synchronized(runningThreads){      runningThreads.add(t);   } } public void unRegist(Thread t){   synchronized(runningThreads){      runningThreads.remove(t);   } } public static boolean hasThreadRunning() { return (runningThreads.size() > 0);//通過判斷runningThreads是否為空就能知道是否還有線程未執行完 } } 

主線程中代碼: 

long tStart = System.currentTimeMillis(); System.out.println(Thread.currentThread().getName() + "開始");//打印開始標記 for (int ii = 0; ii < threadNum; ii++) {//開threadNum個線程 Thread t = new ImportThread(); t.start(); } while(true){//等待所有子線程執行完 if(!ImportThread.hasThreadRunning()){ break; } Thread.sleep(500); } System.out.println(Thread.currentThread().getName() + "結束.");//打印結束標記 long tEnd = System.currentTimeMillis(); System.out.println("總共用時:"+ (tEnd - tStart) + "millions"); 

打印的結果是: 

main開始 
Thread-1開始... 
Thread-5開始... 
Thread-0開始... 
Thread-2開始... 
Thread-3開始... 
Thread-4開始... 
Thread-5結束. 
Thread-4結束. 
Thread-2結束. 
Thread-0結束. 
Thread-3結束. 
Thread-1結束. 
main結束.          

總共用時:20860millions 

可以看到main線程是等所有子線程全部執行完后才開始執行的。 

================================================================================================= 

上面的方法有一個隱患:如果線程1開始并且結束了,而其他線程還沒有開始此時runningThreads的size也為0,主線程會以為所有線程都執行完了。解決辦法是用一個非簡單類型的計數器來取代List型的runningThreads,并且在線程創建之前就應該設定好計數器的值。 

MyCountDown類 
 

  public class MyCountDown { private int count; public MyCountDown(int count){ this.count = count; } public synchronized void countDown(){ count--; } public synchronized boolean hasNext(){ return (count > 0); } public int getCount() { return count; } public void setCount(int count) { this.count = count; } } 

ImportThread類 

 public class ImportThread extends Thread { private MyCountDown c; public ImportThread(MyCountDown c) { this.c = c; } @Override public void run() { System.out.println(Thread.currentThread().getName() + "開始...");//打印開始標記 //Do something c.countDown();//計時器減1 System.out.println(Thread.currentThread().getName() + "結束. 還有" + c.getCount() + " 個線程");//打印結束標記 } } 

主線程中 

System.out.println(Thread.currentThread().getName() + "開始");//打印開始標記 MyCountDown c = new MyCountDown(threadNum);//初始化countDown for (int ii = 0; ii < threadNum; ii++) {//開threadNum個線程 Thread t = new ImportThread(c); t.start(); } while(true){//等待所有子線程執行完 if(!c.hasNext()) break; } System.out.println(Thread.currentThread().getName() + "結束.");//打印結束標記 

打印結果: 

 main開始 
Thread-2開始... 
Thread-1開始... 
Thread-0開始... 
Thread-3開始... 
Thread-5開始... 
Thread-4開始... 
Thread-5結束. 還有5 個線程 
Thread-1結束. 還有4 個線程 
Thread-4結束. 還有3 個線程 
Thread-2結束. 還有2 個線程 
Thread-3結束. 還有1 個線程 
Thread-0結束. 還有0 個線程 
main結束. 

更簡單的方法:使用java.util.concurrent.CountDownLatch代替MyCountDown,用await()方法代替while(true){...}

ImportThread類 

public class ImportThread extends Thread { private CountDownLatch threadsSignal; public ImportThread(CountDownLatch threadsSignal) { this.threadsSignal = threadsSignal; } @Override public void run() { System.out.println(Thread.currentThread().getName() + "開始..."); //Do somethings threadsSignal.countDown();//線程結束時計數器減1 System.out.println(Thread.currentThread().getName() + "結束. 還有" + threadsSignal.getCount() + " 個線程"); } } 

主線程中 

CountDownLatch threadSignal = new CountDownLatch(threadNum);//初始化countDown for (int ii = 0; ii < threadNum; ii++) {//開threadNum個線程 final Iterator<String> itt = it.get(ii); Thread t = new ImportThread(itt,sql,threadSignal); t.start(); } threadSignal.await();//等待所有子線程執行完 System.out.println(Thread.currentThread().getName() + "結束.");//打印結束標記 

打印結果: 

main開始 
Thread-1開始... 
Thread-0開始... 
Thread-2開始... 
Thread-3開始... 
Thread-4開始... 
Thread-5開始... 
Thread-0結束. 還有5 個線程 
Thread-1結束. 還有4 個線程 
Thread-4結束. 還有3 個線程 
Thread-2結束. 還有2 個線程 
Thread-5結束. 還有1 個線程 
Thread-3結束. 還有0 個線程 
main結束.

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 广州市| 宿州市| 彰化县| 太康县| 利津县| 拉孜县| 临漳县| 横峰县| 前郭尔| 丰县| 余干县| 彝良县| 和顺县| 会宁县| 乌拉特中旗| 临城县| 阳江市| 云霄县| 庆安县| 天柱县| 兴安县| 循化| 固安县| 沅江市| 宣威市| 盐源县| 屏东市| 马龙县| 庆阳市| 崇信县| 双峰县| 蚌埠市| 博兴县| 清流县| 阿合奇县| 如东县| 兴城市| 英德市| 广河县| 安仁县| 洪湖市|