Thread线程是否执行完成,我们可以调用join方法然后等待线程执行完成;那在使用线程池的时候,我们如何知道线程已经执行完成了?本文就带给大家五种判断的方式:
package pool;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @author 百里
*/
public class BaiLiIsShutdownThreadPoolDemo {
/**
* 创建一个最大线程数15的线程池
*/
public static ThreadPoolExecutor pool = new ThreadPoolExecutor(
10,
15,
0L,
TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<>(10));
/**
* 线程执行方法,随机等待0到10秒
*/
private static void sleepMethod(int index){
try {
long sleepTime = new Double(Math.random() * 10000).longValue();
Thread.sleep(sleepTime);
System.out.println("当前线程执行结束: " + index);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 方法一:isTerminated
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 10; i++) {
int index = i;
pool.execute(() -> sleepMethod(index));
}
pool.shutdown();
while (!pool.isTerminated()){
Thread.sleep(1000);
System.out.println("还没停止。。。");
}
System.out.println("全部执行完毕");
}
}
上述代码处理逻辑在主线程中进行循环判断,全部任务是否已经完成。
这里有两个主要方法:
优点 :操作简单。
缺点 :需要关闭线程池。并且日常使用是将线程池注入到Spring容器,然后各个组件中统一用同一个线程池,不能直接关闭线程池。
package pool;
import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author 百里
*/
public class BaiLiIsShutdownThreadPoolDemo {
/**
* 创建一个最大线程数15的线程池
*/
public static ThreadPoolExecutor pool = new ThreadPoolExecutor(
10,
15,
0L,
TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<>(10));
/**
* 线程执行方法,随机等待0到10秒
*/
private static void sleepMethod(int index){
try {
long sleepTime = new Double(Math.random() * 10000).longValue();
Thread.sleep(sleepTime);
System.out.println("当前线程执行结束: " + index);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 方法二:getCompletedTaskCount
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 10; i++) {
int index = i;
pool.execute(() -> sleepMethod(index));
}
//当线程池完成的线程数等于线程池中的总线程数
while (!(pool.getTaskCount() == pool.getCompletedTaskCount())) {
System.out.println("任务总数:" + pool.getTaskCount() + "; 已经完成任务数:" + pool.getCompletedTaskCount());
Thread.sleep(1000);
System.out.println("还没停止。。。");
}
System.out.println("全部执行完毕");
}
}
上述代码处理逻辑还是一样在主线程循环判断,主要就两个方法:
package pool;
import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author 百里
*/
public class BaiLiIsShutdownThreadPoolDemo {
/**
* 创建一个最大线程数15的线程池
*/
public static ThreadPoolExecutor pool = new ThreadPoolExecutor(
10,
15,
0L,
TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<>(10));
/**
* 线程执行方法,随机等待0到10秒
*/
private static void sleepMethod(int index){
try {
long sleepTime = new Double(Math.random() * 10000).longValue();
Thread.sleep(sleepTime);
System.out.println("当前线程执行结束: " + index);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 方法三:CountDownLatch
* @throws Exception
*/
public static void main(String[] args) throws Exception {
//计数器,判断线程是否执行结束
CountDownLatch taskLatch = new CountDownLatch(10);
for (int i = 0; i < 10; i++) {
int index = i;
pool.execute(() -> {
sleepMethod(index);
taskLatch.countDown();
System.out.println("当前计数器数量:" + taskLatch.getCount());
});
}
//当前线程阻塞,等待计数器置为0
taskLatch.await();
System.out.println("全部执行完毕");
}
}
优点 :代码优雅,不需要对线程池进行操作。
缺点 :需要提前知道线程数量;性能较差;还需要在线程代码块内加上异常判断,否则在 countDown之前发生异常而没有处理,就会导致主线程永远阻塞在 await。
package pool;
import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author 百里
*/
public class BaiLiIsShutdownThreadPoolDemo {
/**
* 创建一个最大线程数15的线程池
*/
public static ThreadPoolExecutor pool = new ThreadPoolExecutor(
10,
15,
0L,
TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<>(10));
/**
* 线程执行方法,随机等待0到10秒
*/
private static void sleepMethod(int index){
try {
long sleepTime = new Double(Math.random() * 10000).longValue();
Thread.sleep(sleepTime);
System.out.println("当前线程执行结束: " + index);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static int taskNum = 0; //计数器
/**
* 方法四:公共计数
* @throws Exception
*/
public static void main(String[] args) throws Exception {
Lock lock = new ReentrantLock();
for (int i = 0; i < 10; i++) {
int index = i;
pool.execute(() -> {
sleepMethod(index);
lock.lock();
taskNum++;
lock.unlock();
});
}
while(taskNum < 10) {
Thread.sleep(1000);
System.out.println("还没停止。。。当前完成任务数:" + taskNum);
}
System.out.println("全部执行完毕");
}
}
这种实现其实就是通过加锁计数,然后循环判断。
package pool;
import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author 百里
*/
public class BaiLiIsShutdownThreadPoolDemo {
/**
* 创建一个最大线程数15的线程池
*/
public static ThreadPoolExecutor pool = new ThreadPoolExecutor(
10,
15,
0L,
TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<>(10));
/**
* 线程执行方法,随机等待0到10秒
*/
private static void sleepMethod(int index){
try {
long sleepTime = new Double(Math.random() * 10000).longValue();
Thread.sleep(sleepTime);
System.out.println("当前线程执行结束: " + index);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 方法五:Future
* @throws Exception
*/
public static void main(String[] args) throws Exception {
Future future = pool.submit(() -> sleepMethod(1));
while (!future.isDone()){
Thread.sleep(1000);
System.out.println("还没停止。。。");
}
System.out.println("全部执行完毕");
}
}
优点:使用简单,不需要关闭线程池。
缺点:每个提交给线程池的任务都会关联一个Future对象,这可能会引入额外的内存开销。如果需要处理大量的任务,可能会占用较多的内存。
package pool;
import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 五种判断线程池任务执行完成的方式
* @author 百里
*/
public class BaiLiIsShutdownThreadPoolDemo {
/**
* 创建一个最大线程数15的线程池
*/
public static ThreadPoolExecutor pool = new ThreadPoolExecutor(
10,
15,
0L,
TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<>(10));
/**
* 线程执行方法,随机等待0到10秒
*/
private static void sleepMethod(int index){
try {
long sleepTime = new Double(Math.random() * 10000).longValue();
Thread.sleep(sleepTime);
System.out.println("当前线程执行结束: " + index);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 方法一:isTerminated
* @param args
* @throws InterruptedException
*/
public static void isTerminatedTest(String[] args) throws InterruptedException {
for (int i = 0; i < 10; i++) {
int index = i;
pool.execute(() -> sleepMethod(index));
}
pool.shutdown();
while (!pool.isTerminated()){
Thread.sleep(1000);
System.out.println("还没停止。。。");
}
System.out.println("全部执行完毕");
}
/**
* 方法二:getCompletedTaskCount
* @param args
* @throws InterruptedException
*/
public static void completedTaskCountTest(String[] args) throws InterruptedException {
for (int i = 0; i < 10; i++) {
int index = i;
pool.execute(() -> sleepMethod(index));
}
//当线程池完成的线程数等于线程池中的总线程数
while (!(pool.getTaskCount() == pool.getCompletedTaskCount())) {
System.out.println("任务总数:" + pool.getTaskCount() + "; 已经完成任务数:" + pool.getCompletedTaskCount());
Thread.sleep(1000);
System.out.println("还没停止。。。");
}
System.out.println("全部执行完毕");
}
/**
* 方法三:CountDownLatch
* @throws Exception
*/
public static void countDownLatchTest(String[] args) throws Exception {
//计数器,判断线程是否执行结束
CountDownLatch taskLatch = new CountDownLatch(10);
for (int i = 0; i < 10; i++) {
int index = i;
pool.execute(() -> {
sleepMethod(index);
taskLatch.countDown();
System.out.println("当前计数器数量:" + taskLatch.getCount());
});
}
//当前线程阻塞,等待计数器置为0
taskLatch.await();
System.out.println("全部执行完毕");
}
private static int taskNum = 0;
/**
* 方法四:公共计数
* @throws Exception
*/
public static void countTest(String[] args) throws Exception {
Lock lock = new ReentrantLock();
for (int i = 0; i < 10; i++) {
int index = i;
pool.execute(() -> {
sleepMethod(index);
lock.lock();
taskNum++;
lock.unlock();
});
}
while(taskNum < 10) {
Thread.sleep(1000);
System.out.println("还没停止。。。当前完成任务数:" + taskNum);
}
System.out.println("全部执行完毕");
}
/**
* 方法五:Future
* @throws Exception
*/
public static void futureTest(String[] args) throws Exception {
Future future = pool.submit(() -> sleepMethod(1));
while (!future.isDone()){
Thread.sleep(1000);
System.out.println("还没停止。。。");
}
System.out.println("全部执行完毕");
}
}
分享标题:五种判断线程池任务执行完成的方式
URL标题:http://www.shufengxianlan.com/qtweb/news19/422369.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联