
最近写小玩具的时候用到了 CountDownLatch 计数器,然后顺便想了想判断线程池全部结束有多少种方法。
在网上搜了下,可能有些没找到,但是我找到的有(所有方法都是在 ThreadPoolExecutor 线程池方法下测试的):
好嘞,现在开始一个一个介绍优缺点和简要原理;
先创建一个 static 线程池,后面好几个例子就不一一创建了,全部用这个就行了:
然后再准备一个通用的睡眠方法:
这个方法就是为了测试的时候区分线程执行完毕的下顺序而已。
好嘞,准备完毕,现在开始。
首先贴上测试代码:
这一种方式就是在主线程中进行循环判断,全部任务是否已经完成。
这里有两个主要方法:
通俗点讲,就是在执行全部任务后,对线程池进行 shutdown() 有序关闭,然后循环判断 isTerminated() ,线程池是否全部完成。
类似方法扩展:
还是一样,贴上代码:
还是一样在主线程循环判断,主要就两个方法:
这个好理解,总任务数等于已完成任务数,就表示全部执行完毕。
其他 :
最后扯两句,因为我用 main 方法运行的,跑完后 main 没有结束,是因为非守护线程如果不终止,程序是不会结束的。而线程池 Worker 线程里写了一个死循环,而且被设置成了非守护线程。
这种方法是我比较常用的方法,先看代码:
这种方法,呃,应该是看起来比较高级的,我也不知道别的大佬怎么写的,反正我就用这个。
这个方法需要介绍下这个工具类 CountDownLatch 。先把这种方式的优缺点写了,后面再详细介绍这个类。
CountDownLatch 是 JDK 提供的一个同步工具,它可以让一个或多个线程等待,一直等到其他线程中执行完成一组 *** 作。
常用的方法有 countDown 方法和 await 方法, CountDownLatch 在初始化时,需要指定用给定一个整数作为计数器。
当调用 countDown 方法时,计数器会被减1;当调用 await 方法时,如果计数器大于0时,线程会被阻塞,一直到计数器被 countDown 方法减到0时,线程才会继续执行。
计数器是无法重置的,当计数器被减到0时,调用 await 方法都会直接返回。
这种方式其实和 CountDownLatch 原理类似。
先维护一个静态变量
然后在线程任务结束时,进行静态变量 *** 作:
其实就是加锁计数,循环判断。
Future 是用来装载线程结果的,不过,用这个来进行判断写代码总感觉怪怪的。
因为 Future 只能装载一条线程的返回结果,多条线程总不能用 List 在接收 Future 。
这里就开一个线程做个演示:
这种方式就不写优缺点了,因为 Future 的主要使用场景并不是用于判断任务执行状态。
itjobJava老师讲过:1)线程堆栈概述及基础知识
2)线程堆栈的生成原理以及相关工具
3)不同JVM线程堆栈的格式的差异(SunHotSpot、IBMJRE、OracalJRockit)
4)线程堆栈日志介绍以及解析方法
5)线程堆栈的分析和相关的技术
6)常见的问题模板(线程竟态、死锁、IO调用挂死、垃圾回收/问题、死循环等)
7)线程堆栈问题实例分析
我希望这一系列的培训能给你带来确实的帮助,所以请持续关注每周的文章更新。
但是如果我在学习过程中有疑问或者无法理解文章中的内容该怎么办?
不用担心,把我当做你的导师就好。任何关于线程堆栈的问题都可以咨询我(前提是问题不能太low)。请随意选择下面的几种方式与我取得联系:
1)直接本文下面发表评论(不好意思的话可以匿名)
2)将你的线程堆栈数据提交到RootCauseAnalysisforum
3)发Email给我,地址是@@hotmail
能帮我分析我们产品上遇到的问题么?
当然可以,如果你愿意的话可以把你的堆栈现场数据通过邮件或论坛RootCauseAnalysisforum发给我。处理实际问题是才是学习提升技能的王道。
我真心期望大家能够喜欢这个培训。所以我会尽我所能去为你提供高质量的材料,并回答大家的各种问题。
在介绍线程堆栈分析技术和问题模式之前,先要给大家讲讲基础的内容。所以在这篇帖子里,我将先覆盖到最基本的内容,这样大家就能更好的去理解JVM、中间件、以及JavaEE容器之间的交互。
JavaVM概述
Java虚拟机是JaveEE平台的基础。它是中间件和应用程序被部署和运行的地方。
JVM向中间件软件和你的Java/JavaEE程序提供了下面这些东西:
_(二进制形式的)Java/JavaEE程序运行环境
_一些程序功能特性和工具(IO基础设施,数据结构,线程管理,安全,监控等等)
_借助垃圾回收的动态内存分配与管理
你的JVM可以驻留在许多的 *** 作系统(Solaris,AIX,Windows等等)之上,并且能根据你的物理服务器配置,你可以在每台物理/虚拟服务器上安装1到多个JVM进程
JVM与中间件之间的交互
下面这张图展示了JVM、中间件和应用程序之间的高层交互模型。
如你所见,标准JavaEE应用程序的线程的分配实在中间件内核与JVM之间完成的。(当然也有例外,应用程序可以直接调用API来创建线程,这种做法并不常见,而且在使用的过程中也要特别的小心)
同时,请注意一些线程是由JVM内部来进行管理的,典型的例子就是垃圾回收线程,JVM内部使用这个线程来做并行的垃圾回收处理。
因为大多数的线程分配都是由JavaEE容器完成的,所以能够理解和认识线程堆栈跟踪,并能从线程堆栈数据中识别出它来,对你而言很重要这可以让你能够快速的知道JavaEE容器正要执行的是什么类型的请求
从一个线程转储堆栈的分析角度来看,你将能了解从JVM发现的线程池之间的不同,并识别出请求的类型
最后一节会向你提供对于HotSopVM而言什么是JVM线程堆栈的一个概述,还有你将会遇到的各种不同的线程而对IBMVM线程堆栈形式详细内容将会在第四节向你提供
请注意你可以从根本原因分析论坛获得针对本文的线程堆栈示例
JVM线程堆栈——它是什么
JVM线程堆栈是一个给定时间的快照,它能向你提供所有被创建出来的Java线程的完整清单
如果任务是有返回结果的,结合callable接口使用线程池返回Futrue,然后遍历所有Futerue获取结果,所有结果都返回则执行完毕
如果没有返回结果,则使用CounDownLatch类实现
如果用多线程的话,相直接获取是没有办法的,因为这个程序是在另一个线程中执行的,当前线程会不等它执行完,就把后面的代码执行掉了
变通的方法,把这个方法执行的结果赋值给一个静态变量,然后读取这个静态变量的值~~~
如果有多个值,你可以把这些值放到一到静态的数组或是hashtable中~~~
其实你这个思路是错误的:
根据你的说明,你是想在每个页面都有去执行这个方法,而且还要获取结果。
1、这个线程和你的当前页面不在同一个线程,当前页面并不知道你这个ThreadTryRequest在别的线程中是什么样的状态,当前页面的代码也不会等你这个这个线程执行完就执行掉了,所以你不可能马上拿到这个线程的值的。
2、你这个应用,明显不该用异步的线程来执行,如果要用同步模式,我不知道你这个是为了什么目的把它放到线程中执行,因为你用同步模式,你想等这个线程的执行结果,等的时间和在页面顺序执行是一样的甚至更多~~~
你可以说一下你的目的是什么吗? 就你的描述来看,你根本没必要用线程。。。
从你的代码来看,你可能是想提高页面打开速度,把执行慢的代码放到线程中执行。。。 如果从这个思路来看是对的,不过光这样可不用,你还得用缓存,把执行结果放到缓存中再由线程或是线程池来维护。。。
总之,在一个页面中执行这么低效率的代码,整个解决方案就有问题。。。
===================================================================
public string ThreadTryRequest(string strUrl, string parm)
{
Thread thrOne = new Thread(thisThreadProc); //创建线程
ThreadParameter parameter = new ThreadParameter(); //实例化ThreadParameter对象,并赋值
parameterStrUrl = strUrlToString();
parameterparm = parmToString();
thrOneStart(parameter); //开启线程
return strState; //返回字符串
}
你想在这里就获取到值 那是获取不到的 return strState; 执行了
thisThreadProc(parameter) 还没执行完了,这个时候strState 还没被赋值,
所以我说你的思路是错误的
你想当时就知道一个线程的执行结果,除非你等~~~ 要不获取不到的~~~
以上就是关于5种方法,教你判断线程池是否全部完成全部的内容,包括:5种方法,教你判断线程池是否全部完成、你如何在Java中获取线程堆栈、Java如何判断线程池所有任务是否执行完毕等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)