• 多线程处理同一个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));  
        }  
    }
  • 相关阅读:
    设计模式总结——程序猿的武功秘籍(上)
    php获取分类以下的全部子类方法
    TypeError: Cannot read property &#39;style&#39; of null 错误解决
    Java抽象类
    PHP_SELF、 SCRIPT_NAME、 REQUEST_URI差别
    [WPF]使用Pack URI路径訪问二进制资源
    Android JNI编程(五)——C语言的静态内存分配、动态内存分配、动态创建数组
    Android JNI编程(四)——C语言多级指针、数组取值、从控制台输入数组
    Android JNI编程(三)——C语言指针的初步认识、指针变量、互换两个数、函数返回多个值
    Android JNI编程(二)——C语言的基本数据类型,输出函数,输入函数
  • 原文地址:https://www.cnblogs.com/wangfl/p/10266374.html
Copyright © 2020-2023  润新知