主線程等待所有子線程執行完成之后再繼續往下執行的解決方案


問題背景:

目前需要解析十多個Excel文件並將數據導入到數據庫,文件導出完成之后還有后續步驟需要處理,例如更新批次狀態。
如果采用單線程的方式順序去處理每個文件的話,感覺有點慢,雖說不算是特別慢,但是由於用戶需要等待導入結果,
考慮到用於體驗問題,因此需要坐下性能優化。既然是性能優化,基本都是考慮到使用多線程並發處理 。但是多線線程有個問題,
就是啟動多個線程后,如何讓當前線程等待這些子線程執行完畢,因為需要根據所以子線程的執行結果來更新批次狀態
 
解決方案1:
基本思路是這樣:
每個SubThread子線程類實例有個自己的狀態 99-初始化  0-執行成功 1-執行失敗,當執行完畢之后,將狀態修改為0或者1
MainThread 主線程類中有個List,用來登記所有子線程。子線程的創建通過主線程來創建,每次創建之后,都會將子線程添加到List中。
所有子線程創建完成之后,通過主線程的start方法啟動所有子線程,並通過一個while循環來遍歷List中的所有子線程的狀態,
判斷是否存在狀態為99的,如果沒有,則便是全部子線程執行完畢
/**
 * 子線程類
 * @author Administrator
 *
 */
public class SubThread implements Runnable{
    
    private int status = 99; //99-初始化  0-執行成功 1-執行失敗 
 
    public void run() {
        System.out.println("開始執行...");
        try{
            Thread.sleep(2000);
        }catch(Exception e){
            e.printStackTrace();
        }
        status=0;
        System.out.println("執行完畢...");
    }
 
    public int getStatus() {
        return status;
    }
 
    public void setStatus(int status) {
        this.status = status;
    }
}  
/**
 * 主線程類
 * @author Administrator
 *
 */
public class MainThread {
    private List<SubThread> subThreadList = new ArrayList<SubThread>();
    
    /**
     * 創建子線程
     * @return
     */
    public SubThread createSubThread(){
        SubThread subThread = new SubThread();
        subThreadList.add(new SubThread());
        return subThread;
    }
    
    public boolean start(){
        for(SubThread subThread : subThreadList){
            new Thread(subThread).start();
        }
        
        /**
         * 監控所有子線程是否執行完畢
         */
        boolean continueFlag = true;
        while(continueFlag){
            for(SubThread subThread : subThreadList){
                if(subThread.getStatus()==99){
                    continueFlag = true;
                    break;
                }
                continueFlag = false;
            }
        }
        
        /**
         * 判斷子線程的執行結果
         */
        boolean result = true;
        for(SubThread subThread : subThreadList){
            if(subThread.getStatus()!=0){
                result = false;
                break;
            }
        }
        
        return result;
    }
 
}  
測試代碼:

    public static void main(String[] args) {
        MainThread main = new MainThread();
        main.createSubThread();
        main.createSubThread();
        main.createSubThread();
        boolean result = main.start();
        System.out.println(result);
    }
 
 
解決方案2:
通過計數器方式解決。 基本思路如下:
計數器類 CountLauncher 負責記錄正在執行的子線程的總數,所有的子線程共享該計數器類對象,當子線程執行完畢之后,調用計數器的counDown()方法進行計數器減1.
主線程通過計數器類來判斷是否所有子線程都執行完畢。
/**
 * 計數器類
 * @author Administrator
 *
 */
public class CountLauncher {
    private int count;
    
    public CountLauncher(int count){
        this.count = count;
    }
    
    public synchronized void countDown(){
        count --;
    }
 
    public int getCount() {
        return count;
    }
 
    public void setCount(int count) {
        this.count = count;
    }
}  
 
/**
 * 子線程類
 * @author Administrator
 *
 */
public class SubThread implements Runnable{
    
    /**
     * 計數器類對象實例
     */
    private CountLauncher countLauncher;
    
    private int status = 99; //99-初始化  0-執行成功 1-執行失敗 
    
 
    public void run() {
        System.out.println("開始執行...");
        try{
            Thread.sleep(2000);
        }catch(Exception e){
            e.printStackTrace();
        }
        status=0;
        System.out.println("執行完畢...");
        countLauncher.countDown();
    }
 
    public int getStatus() {
        return status;
    }
 
    public void setStatus(int status) {
        this.status = status;
    }
 
    public CountLauncher getCountLauncher() {
        return countLauncher;
    }
 
    public void setCountLauncher(CountLauncher countLauncher) {
        this.countLauncher = countLauncher;
    }
    
}  
 

 

 

/**
 * 主線程類
 * @author Administrator
 *
 */
public class MainThread {
    private List<SubThread> subThreadList = new ArrayList<SubThread>();
    
    /**
     * 創建子線程
     * @return
     */
    public synchronized SubThread createSubThread(){
        SubThread subThread = new SubThread();
        subThreadList.add(new SubThread());
        return subThread;
    }
    
    
    
    public boolean start(){
        CountLauncher countLauncher = new CountLauncher(subThreadList.size());
        for(SubThread subThread : subThreadList){
            subThread.setCountLauncher(countLauncher);
            new Thread(subThread).start();
        }
        
        while(countLauncher.getCount()>0){
            System.out.println(countLauncher.getCount());
        }
        
        /**
         * 判斷子線程的執行結果
         */
        boolean result = true;
        for(SubThread subThread : subThreadList){
            if(subThread.getStatus()!=0){
                result = false;
                break;
            }
        }
        
        return result;
    }
    
    /**
     * 測試實例
     */
    public static void main(String[] args) {
        
        MainThread main = new MainThread();
        main.createSubThread();
        main.createSubThread();
        main.createSubThread();
        boolean result = main.start();
        System.out.println(result);
    }
 
}  
 
 
解決方案3(推薦):
該方法的處理方式同解決方案2 ,只不過使用的是Java自帶的計數器類 java.util.concurrent.CountDownLatch。
還有一點就是不需要在主線程中通過while來監控所有子線程,是否通過調用它的await方法進行等待所有子線程的執行完畢。
使用計數器時,需要注意的一點是:子線程中調用countDown()方法時一定要放在最后來執行,否則會出現子線程未執行完畢,主線程就開始往下執行了。
因為一定計數器為0,就會自動喚醒主線程的。
/**
 * 子線程
 * @author Administrator
 *
 */
public class SubThread implements Runnable{
    
    private int status =99;
    private CountDownLatch threadsSignal;
 
    @Override
    public void run(){
        System.out.println("開始執行...");
        try{
            Thread.sleep(2000);
        }catch(Exception e){
            e.printStackTrace();
        }
        status=0;
        System.out.println("執行完畢...");
        threadsSignal.countDown();
    }
 
    public int getStatus() {
        return status;
    }
 
    public void setStatus(int status) {
        this.status = status;
    }
 
 
    public CountDownLatch getThreadsSignal() {
        return threadsSignal;
    }
 
    public void setThreadsSignal(CountDownLatch threadsSignal) {
        this.threadsSignal = threadsSignal;
    }
}  
 
public class MainThread {
    
    public List<SubThread> subThreadList = new ArrayList<SubThread>();
    
    /**
     * 創建子線程
     * @param clazzPath
     * @param methodName
     * @return
     */
    public SubThread createSubThread(){
        SubThread subThread = new SubThread();
        subThreadList.add(subThread);
        return subThread;
    }
    
    
    /**
     * 啟動線程
     */
    public int start() throws Exception{
        
        CountDownLatch threadSignal = new CountDownLatch(subThreadList.size());
        for(SubThread subThread :subThreadList){
            subThread.setThreadsSignal(threadSignal);
            Thread thread = new Thread(subThread);
            thread.start();
        }
        threadSignal.await();
        System.out.println("所有子線程執行完畢...");
        for(SubThread subThread :subThreadList){
            if(subThread.getStatus()!=0){
                return 1;
            }
        }
        
        return 0;
    }
    
    public static void main(String[] args) throws Exception{
        MainThread main = new MainThread();
        main.createSubThread();
        main.createSubThread();
        main.createSubThread();
        main.createSubThread();
        int result = main.start();
        System.out.println("執行結果:" + result);
    }
    
 
}  

 

 

 
 

 






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM