Java ThreadPoolExecutor中的死锁
当Java ThreadPoolExecutor中的死锁,java,concurrency,Java,Concurrency,当ThreadPoolExecutor停在execute(Runnable)函数中,而所有ThreadPool线程都在getTaskfunc中等待时,遇到一种情况,工作队列为空 有人有什么想法吗 ThreadPoolExecutor是使用ArrayBlockingQueue和corePoolSize==maximumPoolSize=4创建的 [编辑]更准确地说,线程在ThreadPoolExecutor.exec(Runnable命令)func中被阻塞。它有要执行的任务,但没有执行 [Edit
ThreadPoolExecutor
停在execute(Runnable)
函数中,而所有ThreadPool
线程都在getTask
func中等待时,遇到一种情况,工作队列为空
有人有什么想法吗
ThreadPoolExecutor
是使用ArrayBlockingQueue
和corePoolSize==maximumPoolSize=4
创建的
[编辑]更准确地说,线程在ThreadPoolExecutor.exec(Runnable命令)
func中被阻塞。它有要执行的任务,但没有执行
[Edit2]执行器在工作队列中的某个位置被阻止(ArrayBlockingQueue
)
[Edit3]调用堆栈:
thread = front_end(224)
at sun.misc.Unsafe.park(Native methord)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:158)
at
java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:747)
at
java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:778)
at
java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1114)
at
java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:186)
at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:262)
at java.util.concurrent.ArrayBlockingQueue.offer(ArrayBlockingQueue.java:224)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:653)
at net.listenThread.WorkersPool.execute(WorkersPool.java:45)
同时,工作队列为空(使用远程调试进行检查)
[Edit4]使用线程池执行器的代码
:
public WorkersPool(int size) {
pool = new ThreadPoolExecutor(size, size, IDLE_WORKER_THREAD_TIMEOUT, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(WORK_QUEUE_CAPACITY),
new ThreadFactory() {
@NotNull
private final AtomicInteger threadsCount = new AtomicInteger(0);
@NotNull
public Thread newThread(@NotNull Runnable r) {
final Thread thread = new Thread(r);
thread.setName("net_worker_" + threadsCount.incrementAndGet());
return thread;
}
},
new RejectedExecutionHandler() {
public void rejectedExecution(@Nullable Runnable r, @Nullable ThreadPoolExecutor executor) {
Verify.warning("new task " + r + " is discarded");
}
});
}
public void execute(@NotNull Runnable task) {
pool.execute(task);
}
public void stopWorkers() throws WorkersTerminationFailedException {
pool.shutdownNow();
try {
pool.awaitTermination(THREAD_TERMINATION_WAIT_TIME, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new WorkersTerminationFailedException("Workers-pool termination failed", e);
}
}
}
公共工作池(整数大小){
pool=新的ThreadPoolExecutor(大小、大小、空闲线程\u工作线程\u超时、TimeUnit.SECONDS、新的ArrayBlockingQueue(工作队列\u容量),
新螺纹工厂(){
@NotNull
private final AtomicInteger threadsCount=新的AtomicInteger(0);
@NotNull
公共线程newThread(@NotNull Runnable r){
最终螺纹=新螺纹(r);
setName(“net_worker_”+threadscont.incrementAndGet());
返回线程;
}
},
新的RejectedExecutionHandler(){
public void rejectedExecution(@Nullable Runnable r、@Nullable ThreadPoolExecutor executor){
验证。警告(“新任务”+r+“被丢弃”);
}
});
}
public void execute(@NotNull可运行任务){
pool.execute(任务);
}
public void stopWorkers()抛出workerTerminationFailedException{
pool.shutdownNow();
试一试{
等待终止(线程终止等待时间,时间单位秒);
}捕捉(中断异常e){
抛出新WorkersTerminationFailedException(“Workers池终止失败”,e);
}
}
}
我在ThreadPoolExecutor
的execute(Runnable)
的代码中没有看到任何锁定。唯一的变量是工作队列
。您向线程池执行器提供了哪种类型的阻塞队列
关于僵局的话题:
您可以通过检查完整的线程转储来确认这是死锁,如Windows上的
或UNIX系统上的kill-QUIT
所提供
一旦有了这些数据,就可以检查线程了。以下是以下内容的相关摘录:
对于挂起、死锁或冻结的程序:如果您认为您的程序正在挂起,请生成堆栈跟踪并检查处于MW或CW状态的线程。如果程序处于死锁状态,那么一些系统线程可能会显示为当前线程,因为JVM没有其他事情可做
更简单的一点是:如果您在IDE中运行,能否确保这些方法中没有启用断点。正如前面提到的,这听起来像是正常行为,ThreadPoolExecutor只是在等待做一些工作。如果要停止,您需要拨打:
执行器关闭()
要使其终止,通常后跟一个执行器。等待终止库代码源在下面(实际上是来自的一个类),
-有点复杂-如果我没有弄错的话,增加了对FutureTask重复调用的保护-但似乎不容易死锁-非常简单的线程池用法:
package net.spy.memcached.transcoders;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import net.spy.memcached.CachedData;
import net.spy.memcached.compat.SpyObject;
/**
* Asynchronous transcoder.
*/
public class TranscodeService extends SpyObject {
private final ThreadPoolExecutor pool = new ThreadPoolExecutor(1, 10, 60L,
TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(100),
new ThreadPoolExecutor.DiscardPolicy());
/**
* Perform a decode.
*/
public <T> Future<T> decode(final Transcoder<T> tc,
final CachedData cachedData) {
assert !pool.isShutdown() : "Pool has already shut down.";
TranscodeService.Task<T> task = new TranscodeService.Task<T>(
new Callable<T>() {
public T call() {
return tc.decode(cachedData);
}
});
if (tc.asyncDecode(cachedData)) {
this.pool.execute(task);
}
return task;
}
/**
* Shut down the pool.
*/
public void shutdown() {
pool.shutdown();
}
/**
* Ask whether this service has been shut down.
*/
public boolean isShutdown() {
return pool.isShutdown();
}
private static class Task<T> extends FutureTask<T> {
private final AtomicBoolean isRunning = new AtomicBoolean(false);
public Task(Callable<T> callable) {
super(callable);
}
@Override
public T get() throws InterruptedException, ExecutionException {
this.run();
return super.get();
}
@Override
public T get(long timeout, TimeUnit unit) throws InterruptedException,
ExecutionException, TimeoutException {
this.run();
return super.get(timeout, unit);
}
@Override
public void run() {
if (this.isRunning.compareAndSet(false, true)) {
super.run();
}
}
}
}
包net.spy.memcached.transcoders;
导入java.util.concurrent.ArrayBlockingQueue;
导入java.util.concurrent.Callable;
导入java.util.concurrent.ExecutionException;
导入java.util.concurrent.Future;
导入java.util.concurrent.FutureTask;
导入java.util.concurrent.ThreadPoolExecutor;
导入java.util.concurrent.TimeUnit;
导入java.util.concurrent.TimeoutException;
导入java.util.concurrent.AtomicBoolean;
导入net.spy.memcached.CachedData;
导入net.spy.memcached.compat.SpyObject;
/**
*异步转码器。
*/
公共类代码转换服务扩展了间谍对象{
专用最终ThreadPoolExecutor池=新ThreadPoolExecutor(1,10,60L,
TimeUnit.ms,新的ArrayBlockingQueue(100),
新的ThreadPoolExecutor.DiscardPolicy());
/**
*执行解码。
*/
公共未来解码(最终转码器tc,
最终缓存数据(缓存数据){
assert!pool.isShutdown():“池已关闭。”;
TranscodeService.Task任务=新建TranscodeService.Task(
新的可调用(){
公共电话{
返回tc.decode(缓存数据);
}
});
if(tc.asyncode(cachedData)){
this.pool.execute(任务);
}
返回任务;
}
/**
*关闭游泳池。
*/
公共空间关闭(){
pool.shutdown();
}
/**
*询问此服务是否已关闭。
*/
公共布尔值isShutdown(){
返回池;
}
私有静态类任务扩展了FutureTask{
private final AtomicBoolean isRunning=新的AtomicBoolean(false);
公共任务(可调用可调用){
超级(可调用);
}
@凌驾
public T get()抛出InterruptedException、ExecutionException{
这个。run();
返回super.get();
}
@凌驾
公共T get(长超时,时间单位)抛出InterruptedException,
ExecutionException,TimeoutException{
这个。run();
返回super.get(超时,单位);
}
@凌驾
公开募捐{
if(此.isRunning.compareAndSet(false,true)){
super.run();
}
}
}
}
绝对奇怪
但在编写自己的TPE之前,请尝试: