我的ThreadPoolExecutor没有将任务分配给工作线程。由于我不知道这个问题是如何产生的,所以将解释当前的情况。
CorePoolSize = 15,
Max PoolSize = 100,
KeepAliveTime 5 minutes,
ArrayBlockingQueue of size 1.
目前
executor.getActiveCount() = 0,
executor.getPoolSize() = 100,
executor.getQueue().remainingCapacity() = 0
我可以看到我提交的任务是在ArrayBlockingQueue中但是为什么这100个线程只是坐在线程池中而没有人选择提交的任务。
jconsole中所有具有类似堆栈跟踪的线程
Name: pool-15-thread-182
State: WAITING on java.util.concurrent.locks.ReentrantLock$NonfairSync@16926fe3
Total blocked: 396 Total waited: 66
Stack trace:
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.park(LockSupport.java:156)
java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:811)
java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:842)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2033)
java.util.concurrent.ArrayBlockingQueue.poll(ArrayBlockingQueue.java:347)
java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:955)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:917)
java.lang.Thread.run(Thread.java:682)
代码
初始化:
executor = new ThreadPoolExecutor(CORE_THREADPOOL_SIZE, (int)MAX_THREADPOOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1), new ThreadPoolExecutor.AbortPolicy());
提交任务:
Future<?> futureTask = executor.submit(opmTask);
任务:
class OpmTask implements Runnable {
@Override public void run() {
.... }
}
线程管理杀死阻塞线程
if(future != null && !future.isDone()){
future.cancel(true);
}
// after 30 minutes of above code if still blocking thread running
if(thread.isAlive()){
thread.stop();
}
内部运行一些内部方法
while (true) {
while (InputStream.available() > 0) {
int i = in.read(tmp, 0, 1024);
if (i < 0)
break;
outputStr += new String(tmp, 0, i);
}
if(Thread.interrupted()){
logger.log(Level.SEVERE,"Thread interrupted");
throw new BlockedThreadException("Thread interrupted");
}
}
答案 0 :(得分:1)
从你的例子来看,这有点难以理解。我建议首先制作你的线程守护进程,这样它们就不会阻止你的应用程序关闭。至于你的例子,我看不出任何不当行为。试试这个例子:
Stack trace:
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.park(LockSupport.java:156)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1987)
java.util.concurrent.ArrayBlockingQueue.take(ArrayBlockingQueue.java:322)
java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:957)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:917)
java.lang.Thread.run(Thread.java:682)
请注意,这将永远运行并在一行一行后打印下一行。也不是说我传递的ThreadFactory将执行程序的线程配置为守护进程。
至于你的stacktrace:
ArrayBlockingQueue#take
这并不意味着你的线程被卡住了。 (从技术上讲,它确实如此,但实际上并非如此)。他们正在等待新任务的开展。如果您查看队列实施: public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == 0)
notEmpty.await();
return dequeue();
} finally {
lock.unlock();
}
}
{{1}}
这是他们等待新任务的地方。他们检查队列是否还有其他事情要做,然后等到队列。这自然会发生在你的所有线程上。
我也发现配置有点奇怪。您可以使用最大大小为1的队列配置100个工作程序。这似乎是删除任务的方法。
此外,您没有显示您的任务实现,这意味着我只是猜测您的线程池在异常上的行为。
您的设置似乎正常,但问题在于任务或提交本身。