多線程處理同一個List測試dome

package com.sysware.p2m.task.op.process;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

public class ThreadTese{

  static   class TestRnnubeal extends Thread{
        private String threadName;
        private List<String> list;
        private int startIndex;
        private int endIndex;
        private CountDownLatch countDownLatch;//計數器


      public TestRnnubeal(String threadName, List<String> list, int startIndex, int endIndex,CountDownLatch countDownLatch) {
          this.threadName = threadName;
          this.list = list;
          this.startIndex = startIndex;
          this.endIndex = endIndex;
          this.countDownLatch = countDownLatch;
      }
        public void run() {
            List<String> subList = list.subList(startIndex, endIndex);
            for(int i=0;i<subList.size();i++){
        //        System.out.println(i);
            }
            System.out.println(threadName+"處理了"+subList.size()+"條!startIndex:"+startIndex+"|endIndex:"+endIndex);
            countDownLatch.countDown();//計數器減1
        }
    }


    public static void main(String[] args) {
        long strTime2 = System.currentTimeMillis();
        List<String> tmpList = new ArrayList<String>();
        for (int i = 0; i < 13000000; i++) {
            tmpList.add("test" + i);
        }

        int length = tmpList.size();
        int num = 10; //初始線程數

        //啓動多線程
        if(num > length){
            num = length;
        }
        int baseNum = length / num;
        int remainderNum = length % num;
        int end  = 0;
        long end2 = System.currentTimeMillis();

        long strTime = System.currentTimeMillis();
        List<Thread> list =new ArrayList<Thread>();
        CountDownLatch countDownLatch = new CountDownLatch(num); //建立一個線程計數器 傳入線程數
        for (int i = 0; i < num; i++) {
            int start = end ;
            end = start + baseNum;
            if(i == (num-1)){
                end = length;
            }else if( i < remainderNum){
                end = end + 1;
            }

                 Thread thread = new TestRnnubeal("線程[" + (i + 1) + "] ",  tmpList,start , end,countDownLatch);
                 thread.start();
       //          list.add(thread); //也能夠使用join方法;
        }

//        for (Thread thread:list){
//            try {
//                thread.join();
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
     //   }
      
      
  try {
            boolean timeoutFlag = countDownLatch.await(50, TimeUnit.SECONDS);//設置線程超時時間 同await()同樣;
            if (timeoutFlag) {
               System.out.println("全部線程執行完畢");
            }else {
                System.out.println("執行超時");
            }
            //   countDownLatch.await();//阻止主線程 當計數器爲0時放開(說明全部子線程以執行完畢)
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

 

long endTime = System.currentTimeMillis(); System.out.println("用時"+ (endTime-strTime) + "毫秒"+"處理數據用時"+(end2-strTime2)+"毫秒"); } }

注意:若是子線程中會有異常,那麼countDownLatch.countDown()應該寫在finally裏面,這樣才能保證異常後也能對計數器減1,不會讓主線程永遠等待。java

另外,await()方法還有一個實用的重載方法:public booleanawait(long timeout, TimeUnit unit),設置超時時間。多線程

例如上面的代碼,想要設置超時時間10秒,到了10秒不管是否倒數完成到0,都會再也不阻塞主線程。返回值是boolean類型,若是是超時返回false,若是計數到達0沒有超時返回true。併發

 

主線程等待線程池this

Java線程池java.util.concurrent.ExecutorService是很好用的多線程管理方式。ExecutorService的一個方法boolean awaitTermination(long timeout, TimeUnit unit),即阻塞主線程,等待線程池的全部線程執行完成,用法和上面所說的CountDownLatch的public boolean await(long timeout,TimeUnit unit)相似,參數設置一個超時時間,返回值是boolean類型,若是超時返回false,若是線程池中的線程所有執行完成,返回true。spa

因爲ExecutorService沒有相似CountDownLatch的無參數的await()方法,只能經過awaitTermination來實現主線程等待線程池。線程

public class Main  
{  
    public static void main(String[] args)  
    {  
        long start = System.currentTimeMillis();  
          
        // 建立一個同時容許兩個線程併發執行的線程池  
        ExecutorService executor = Executors.newFixedThreadPool(2);  
        for(int i = 0; i < 5; i++)  
        {  
            Thread thread = new TestThread();  
            executor.execute(thread);  
        }  
        executor.shutdown();  
          
        try  
        {  
            // awaitTermination返回false即超時會繼續循環,返回true即線程池中的線程執行完成主線程跳出循環往下執行,每隔10秒循環一次  
            while (!executor.awaitTermination(10, TimeUnit.SECONDS));  
        }  
        catch (InterruptedException e)  
        {  
            e.printStackTrace();  
        }  
          
        long end = System.currentTimeMillis();  
        System.out.println("子線程執行時長:" + (end - start));  
    }  
}
相關文章
相關標籤/搜索