多线程处理同一个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,不会让主线程永远等待。

另外,await()方法还有一个实用的重载方法:public booleanawait(long timeout, TimeUnit unit),设置超时时间。

例如上面的代码,想要设置超时时间10秒,到了10秒无论是否倒数完成到0,都会不再阻塞主线程。返回值是boolean类型,如果是超时返回false,如果计数到达0没有超时返回true。

 

主线程等待线程池

Java线程池java.util.concurrent.ExecutorService是很好用的多线程管理方式。ExecutorService的一个方法boolean awaitTermination(long timeout, TimeUnit unit),即阻塞主线程,等待线程池的所有线程执行完成,用法和上面所说的CountDownLatch的public boolean await(long timeout,TimeUnit unit)类似,参数设置一个超时时间,返回值是boolean类型,如果超时返回false,如果线程池中的线程全部执行完成,返回true。

由于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));  
    }  
}

 

posted on 2019-01-14 13:52  天道酬勤,学无止境  阅读(1327)  评论(0编辑  收藏  举报

导航