多线程的项目实战

👉👉请优先查看大佬文章

//1.CountDownLatch,计数
CountDownLatch doneSignal = new CountDownLatch(1000);

//2.创建线程池来存放线程,以防考生数量太多创建太多线程,占用过多资源
ThreadPoolExecutor executor = new ThreadPoolExecutor(50, 150, 60000, TimeUnit.MILLISECONDS, new LinkedBlockingDeque<>());

for (ExaminationModel examineeModel : notExamStudentInfo) {
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            
           // 。。。。。。打印试卷的逻辑
            
            } finally {             
            	// 每执行完一个线程,数量减1      
                doneSignal.countDown();
            }
        }
    });
    //3. 将任务添加到线程池
    executor.execute(thread);
}

//  4. 为了让所有的试卷都生成之后再执行压缩以及删除PDF文件,所以需要让主线程等待子线程执行完之后再执行await
try {
	// 主线程等待
    doneSignal.await();
    System.out.println("线程运行时间:" + (System.currentTimeMillis() - startTime) + "ms");
} catch (InterruptedException e) {
    log.error(e.getMessage(), e);
}

//5. 关闭线程池(所有线程执行完关闭线程池)
executor.shutdown();

// 6. 将所有试卷打包zip
boolean flag = fileToZip();

知识点讲解:

之所以用线程池,是因为防止产生过多的线程,从而造成线程来回切换,而造成的形成损失
CountDownLatch:它的作用是允许1或N个线程等待其他线程完成执行,在这用它是因为 要把所有的试卷,打包成zip压缩包,所以主线程要等所有的子线程即生成试卷要执行完才能打包,用到了CountDownLatch的await()和countDown()方法,有关CountDownLatch更多讲解,参见:https://www.cnblogs.com/skywang12345/p/3533887.html
我这创建的核心线程为50,最大线程为150,更具电脑cpu性能设置,执行程序打印线程号,线程号一直超不过50,是因为任务队列使用的是LinkedBlockingDeque,大小为Integer.MAX_VALUE(Integer.MAX_VALUE=7fffffff(十六进制) = 2147483647(十进制)),任务队列一直没有满,具体原因详情参见:https://mp.csdn.net/mdeditor/90082697#

为什么不用join()
使用join()可能出现的问题:

join()后面的代码可能提前完成,这样打包的数据就不全了
join()过程中可能被打断了,这样系统就会抛异常( 因为底层调用的是wait() ),如果不想让程序判断就得做各种异常的判断,比较麻烦

————————————————
版权声明:本文为CSDN博主「王如霜」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wrs120/article/details/90634863
posted @ 2022-03-15 21:13  Lz_蚂蚱  阅读(343)  评论(0)    收藏  举报