扩展ThreadPoolExecutor打印线程错误堆栈

在使用JDK Executors产生线程池执行任务时,如果使用threadPool.submit(Runnable)来提交任务,且不调用future.get时,如果线程发生错误,程序是不会打印错误堆栈的,比如下面的程序,当i==0时,100/i发生运行时异常,只有四组输出(应该有五组),但是程序不会打印任何异常信息,

import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class DivTask implements Runnable{

	int a,b;
	public DivTask(int a,int b){
		this.a = a;
		this.b = b;
	}
	
	@Override
	public void run() {
		double re = a/b;
		System.out.println(re);
	}
	
	public static void main(String[] args) {
		ThreadPoolExecutor pool = new ThreadPoolExecutor(0,Integer.MAX_VALUE,
				0L,TimeUnit.SECONDS,new SynchronousQueue<Runnable>());
		for(int i=0;i<5;i++){
			pool.submit(new DivTask(100, i));
		}
	}
}

输出为:

100.0
25.0
33.0
50.0

我们可以将submit方法改成execute方法或者使用 Future  re = pools.submit(new DivTask(100,i)); re.get()来打印错误堆栈,改后输出如下:

Exception in thread "pool-1-thread-1" java.lang.ArithmeticException: / by zero
	at test.DivTask.run(DivTask.java:17)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
	at java.lang.Thread.run(Thread.java:722)
100.0
25.0
50.0
33.0

我们打印了堆栈,看到了错误,却看不到任务是在哪里提交到,要想看到错误,需要扩展线程池,如下:

package test;

import java.util.concurrent.Future;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class DivTask implements Runnable{

	int a,b;
	public DivTask(int a,int b){
		this.a = a;
		this.b = b;
	}
	
	@Override
	public void run() {
		double re = a/b;
		System.out.println(re);
	}
	
	public static void main(String[] args) {
		ThreadPoolExecutor pool = new ThreadPoolExecutor(0,Integer.MAX_VALUE,
				0L,TimeUnit.SECONDS,new SynchronousQueue<Runnable>()){

					@Override
					public void execute(Runnable command) {
						
						Runnable newCommand = wrap(command,clientTrace(),Thread.currentThread().getName());
						super.execute(newCommand);
					}

					@Override
					public Future<?> submit(Runnable task) {
						Runnable newTask = wrap(task,clientTrace(),Thread.currentThread().getName());
						return super.submit(newTask);
					}
					
					private Runnable wrap(final Runnable task, final Exception clientStack,
							String clientThreadName){
						
						return new Runnable(){
							@Override
							public void run() {
								try{
									task.run();
								}catch(Exception e){
									clientStack.printStackTrace();
									throw e;
								}
							}
						}; //return语句结束
					}
					
					private Exception clientTrace(){
						return new Exception("Client stack trace");
					}
			
		};
		for(int i=0;i<5;i++){
			pool.execute(new DivTask(100, i));
		}
	}
}
上面程序重写了ThreadPoolExecutor的executor和submit方法,并且为任务提供了一个包装函数,就可以打印出在哪里提交的任务了,下面红色部分:

100.0
25.0
33.0
50.0
java.lang.Exception: Client stack trace
at test.DivTask$1.clientTrace(DivTask.java:56)
at test.DivTask$1.execute(DivTask.java:29)
at test.DivTask.main(DivTask.java:61)

Exception in thread "pool-1-thread-1" java.lang.ArithmeticException: / by zero
at test.DivTask.run(DivTask.java:18)
at test.DivTask$1$1.run(DivTask.java:46)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722
)


参考《实战java高并发程序设计》3.2.8堆栈去哪里了

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值