Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/373.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java ThreadPoolExecutor中的死锁_Java_Concurrency - Fatal编程技术网

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之前,请尝试: