Java并发程序设计(7)线程池之异常终止和正常关闭

1.1. 线程池中的线程的异常终止

如果线程池中的线程的任务代码发生异常导致线程终止,线程池会自动创建一个新线程。

对于各种类型的线程池,都是如此。以下代码在单个线程的线程池中抛出一个异常,可以发现后续任务中输出的每个tid的值都不相同。

ExecutorService  executorService = Executors.newSingleThreadExecutor();

for(int j=0;j<10;j++){

final int t = j;

executorService.execute( new Runnable(){

@Override

public void run() {

for(int i=0;i<4;i++){

System.out.println("t:" + t + "," + "i:" + i + ", tid:" + Thread.currentThread().getId());

int a = 3 /0;//产生/ by zero异常,线程终止。新任务将创建新线程。

}

}

});

}

输出信息中可以看到对每个任务(t),线程id(tid)都不同。

t:0,i:0, tid:8

t:1,i:0, tid:10

Exception in thread "pool-1-thread-1" t:2,i:0, tid:11

Exception in thread "pool-1-thread-2" Exception in thread "pool-1-thread-3" java.lang.ArithmeticException: / by zero

t:3,i:0, tid:12

at com.test.concurrence.ThreadPoolTest$3.run(ThreadPoolTest.java:58)

at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

at java.lang.Thread.run(Unknown Source)

Exception in thread "pool-1-thread-4" java.lang.ArithmeticException: / by zero

at com.test.concurrence.ThreadPoolTest$3.run(ThreadPoolTest.java:58)

t:4,i:0, tid:13

at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

at java.lang.Thread.run(Unknown Source)

java.lang.ArithmeticException: / by zero

at com.test.concurrence.ThreadPoolTest$3.run(ThreadPoolTest.java:58)

at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

t:5,i:0, tid:14

at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

at java.lang.Thread.run(Unknown Source)

java.lang.ArithmeticException: / by zero

at com.test.concurrence.ThreadPoolTest$3.run(ThreadPoolTest.java:58)

at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

at java.lang.Thread.run(Unknown Source)

t:6,i:0, tid:15

Exception in thread "pool-1-thread-6" Exception in thread "pool-1-thread-5" Exception in thread "pool-1-thread-7" java.lang.ArithmeticException: / by zero

at com.test.concurrence.ThreadPoolTest$3.run(ThreadPoolTest.java:58)

at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

t:7,i:0, tid:16

at java.lang.Thread.run(Unknown Source)

java.lang.ArithmeticException: / by zero

t:8,i:0, tid:17 at com.test.concurrence.ThreadPoolTest$3.run(ThreadPoolTest.java:58)

at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

at java.lang.Thread.run(Unknown Source)

Exception in thread "pool-1-thread-9" Exception in thread "pool-1-thread-8" java.lang.ArithmeticException: / by zero

t:9,i:0, tid:18 at com.test.concurrence.ThreadPoolTest$3.run(ThreadPoolTest.java:58)

at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

at java.lang.Thread.run(Unknown Source)

Exception in thread "pool-1-thread-10" java.lang.ArithmeticException: / by zero

at com.test.concurrence.ThreadPoolTest$3.run(ThreadPoolTest.java:58)

at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

at java.lang.Thread.run(Unknown Source)

java.lang.ArithmeticException: / by zero

at com.test.concurrence.ThreadPoolTest$3.run(ThreadPoolTest.java:58)

at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

at java.lang.Thread.run(Unknown Source)

java.lang.ArithmeticException: / by zero

at com.test.concurrence.ThreadPoolTest$3.run(ThreadPoolTest.java:58)

at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

at java.lang.Thread.run(Unknown Source)

1.2. 线程池的终止

shutdownNow()和shutdown()都可以终止线程池,两者都可以终止线程池,阻止新任务的提交。

shutdownNow()会停止当前正在执行的任务,清除已提交但是尚未运行的任务,然后终止线程池。

shutdown()会等待已经提交的所有任务执行完毕才终止线程池。

ExecutorService  executorService = Executors.newFixedThreadPool(2);

for(int j=0;j<10;j++){

final int t = j;

executorService.execute( new Runnable(){

@Override

public void run() {

for(int i=0;i<4;i++){

String s = "t:" + t + "," + "i:" + i + ", tid:" + Thread.currentThread().getId();

System.out.println(s);

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

});

}

executorService.shutdownNow();

t:0,i:0, tid:8

end.

t:1,i:0, tid:9

java.lang.InterruptedException: sleep interrupted

t:0,i:1, tid:8

at java.lang.Thread.sleep(Native Method)

at com.test.concurrence.ThreadPoolTest$1.run(ThreadPoolTest.java:27)

at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

at java.lang.Thread.run(Unknown Source)

java.lang.InterruptedException: sleep interrupted

at java.lang.Thread.sleep(Native Method)

at com.test.concurrence.ThreadPoolTest$1.run(ThreadPoolTest.java:27)

at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

at java.lang.Thread.run(Unknown Source)

t:1,i:1, tid:9

t:0,i:2, tid:8

t:1,i:2, tid:9

t:0,i:3, tid:8

t:1,i:3, tid:9

时间: 2024-10-17 11:02:59

Java并发程序设计(7)线程池之异常终止和正常关闭的相关文章

Java并发程序设计(6)线程池之线程数量的控制

1.1. ExecutorService ExecutorService是线程池的接口. Executors是用于创建不同线程池的工具类. 1.2. 线程数量固定的线程池 ExecutorService executorService = Executors.newFixedThreadPool(2); for(int j=0;j<10;j++){ final int t = j; executorService.execute( new Runnable(){ @Override public

Java并发程序设计(8)线程池之用于定时器

1.1. 线程池用于定时器 线程池用于定时器调度时,只能指定某个时间段后执行任务,而不能指定具体的时间点. 1.2. 只运行一次的定时器 5秒钟后运行指定任务的定时器,定时器任务只会被执行1次. ScheduledExecutorService executorService = Executors.newScheduledThreadPool(3); executorService.schedule( new Runnable(){ @Override public void run() {

Java并发程序设计(10)线程池之任务结果的异常处理

1.1. 任务结果的异常处理 如果任务执行过程中发生异常,则get()方法会产生ExecutionException. ExecutorService executorService = Executors.newFixedThreadPool(2); Future<Integer> future = executorService.submit( new Callable(){ @Override public Integer call() throws Exception { throw

Java并发程序设计(9)线程池之获取任务执行结果

1.1. 获取执行结果 使用Callable接口可以方便的获取任务执行结果. ExecutorService executorService = Executors.newFixedThreadPool(2); Future<Integer> future = executorService.submit( new Callable(){ @Override public Integer call() throws Exception { return 1; } }); try { int r

【转】Java并发编程:线程池的使用

Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间. 那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务? 在Java中可以通过线程池来达到这样的效果.今天我们就来详细讲解一下Java的线程池,首先我们从最核心的ThreadPool

Java并发基础(六) - 线程池

Java并发基础(六) - 线程池 1. 概述 这里讲一下Java并发编程的线程池的原理及其实现 2. 线程池的基本用法 2.1 线程池的处理流程图 该图来自<Java并发编程的艺术>: 从图中我们可以看出当一个新任务到线程池时,线程池的处理流程如下: 线程池首先判断线程池里面线程数是否达到核心线程数.如果不是则直接创建新线程作为核心线程来执行该任务(该线程作为核心线程不会由于任务的完成而销毁),否则进入下一流程. 判断阻塞队列是否已经满了.如果没满则将该任务放入阻塞队列中,等待核心线程处理,

Java并发编程:线程池的使用(转)

Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间. 那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务? 在Java中可以通过线程池来达到这样的效果.今天我们就来详细讲解一下Java的线程池,首先我们从最核心的ThreadPool

Java并发编程:线程池的使用

在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间. 那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务? 在Java中可以通过线程池来达到这样的效果.今天我们就来详细讲解一下Java的线程池,首先我们从最核心的ThreadPoolExecutor类中的方法讲起,

Java 并发编程之线程池的使用

在任务与执行策略之间的隐性耦合 Executor框架可以将任务的提交与任务的执行策略解耦开来(就是独立化).虽然Executor框架为制定和修改执行策略都提供了相当大的灵活性,但并非所有的任务都能适用所有的执行策略 比如: 依赖性任务 比如依赖于执行时序,执行结果或者其他效果,那么任务就带有隐含的依赖性.此时必须小心 地维持这些执行策略以避免产生活跃性问题(死锁等造成执行困难的问题) 使用线程封闭机制的任务 与线程池相比,单线程的Executor能够对并发性做出更强的承诺,它们能确保任务不会并发