3.2.8 堆栈去哪里了:在线程池中寻找堆栈

Posted anxbb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3.2.8 堆栈去哪里了:在线程池中寻找堆栈相关的知识,希望对你有一定的参考价值。

public class TheadFind {
public static class TestThread implements Runnable{
int a,b;

public TestThread(int a,int b) {
this.a=a;
this.b=b;
}

public void run() {
double re=a/b;
System.out.println(re);
}
}

public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(5);

for (int i = 0; i < 5; i++) {
executorService.submit(new TestThread(100,i));
}
}
}

运行结果如下:

100.0
33.0
25.0
50.0

细心的你肯定会说,我们明明是开启了5个线程,为什么会得到4个结果呢,即使是100/0,那么也会报异常,为什么会没有呢。难道是线程池把错了“吃了吗?”。对于我们来说如果发现错误但是没有异常信息那是一件多么可怕的事情啊。

所以线程池好用,但是也存在我们所说的坑啊。上面的问题,最简单的解决方案是 将  submit()方法替换 execute(),运行结果如下:

100.0
Exception in thread "pool-1-thread-1" java.lang.ArithmeticException: / by zero
50.0
at 第三章.堆栈去哪里了.在线程池中寻找堆栈$TestThread.run(在线程池中寻找堆栈.java:19)
33.0
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
25.0
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at java.lang.Thread.run(Thread.java:662)

 

第二种: 

          

Future submit = executorService.submit(new TestThread(100, i));
try {
submit.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}

 

很明显我们发现了错误。所以大家在以后使用线程池的时候  一定要谨慎,一定要避免吃掉异常这一现象。

 

当然 以上只是能满足我们部分的需求,那么为了避免出现此类情况,在初期我们麻烦一点,将其封装下(以下是我给出的范例)

 

package 第三章.堆栈去哪里了;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* Created by zzq on 2018/2/8.
*/
public class TraceThreadPoolExecutor extends ThreadPoolExecutor{
public TraceThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}

public void execute(Runnable task) {
super.execute(wrap(task, clientTrace(Thread.currentThread().getName()), Thread.currentThread().getName()));
}

private Runnable wrap(final Runnable task, final Exception clientTrace, final String name) {
return new Runnable() {
public void run() {
try {
task.run();
} catch (Exception e) {
clientTrace.printStackTrace();
try {
throw e;
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
};
}

private Exception clientTrace(String name) {
return new Exception("Client stack trace------"+name);
}

public static class TestThread implements Runnable{
int a,b;

public TestThread(int a,int b,String name) {
this.a=a;
this.b=b;
Thread.currentThread().setName(name);
}

public void run() {
double re=a/b;
System.out.println(re);
}
}

public static void main(String[] args) {
TraceThreadPoolExecutor traceThreadPoolExecutor=new TraceThreadPoolExecutor(5,5,0l,TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(5));
for (int i = 0; i < 5; i++) {
traceThreadPoolExecutor.execute(new TestThread(100,i,"第--"+i+"个"));
// executorService.execute(new TestThread(100,i));
}
}
}

那么我们就可以定位问题出现的位置,尽快解决。

 

以上是关于3.2.8 堆栈去哪里了:在线程池中寻找堆栈的主要内容,如果未能解决你的问题,请参考以下文章

java线上程序排错经验2 - 线程堆栈分析

位于进程虚拟地址空间中的其他线程的堆栈在哪里?

线程池的堆栈问题

堆栈、数据和指令段在哪里实现?

LINUX线程简介和简单代码案例

你如何在 Java 中获取线程堆栈?