java parking_java.lang.Thread.State:WAITING(parking)

闲话少说,

Tomcat日志报错及堆栈信息:

87e221a7a7345868c4305cbac8026d43.png

6e1012118c7c447f818d9c6a1f200ece.png

因为这个问题,挂了几个节点。

跟踪报错的代码发现代码中用到future.get()方法:

Callable myCallable =createThreadCallable(interfaceName, httpbody, authSeedVo);

Future future =threadPool.submit(myCallable);try{super.sendJson(future.get().toString());

}catch(Exception e) {

logger.error("delsub", "获取子线程时发生异常", e);

}

任务由线程池提供的线程执行,那么这时候主线程则会阻塞,直到任务线程唤醒它们。获取结果时,通过future.get()方法获取:

16bdc2ab68fb5ab4f998970149897a3d.png

当 s<= COMPLETING时,表明任务仍然在执行且没有被取消。如果它为true,那么走到awaitDone方法。

下面来看看awaitDone方法里面干了啥:

/*** Awaits completion or aborts on interrupt or timeout.

*

*@paramtimed true if use timed waits

*@paramnanos time to wait, if timed

*@returnstate upon completion*/

private int awaitDone(boolean timed, longnanos)throwsInterruptedException {final long deadline = timed ? System.nanoTime() + nanos : 0L;

WaitNode q= null;boolean queued = false;for(;;) {if(Thread.interrupted()) {

removeWaiter(q);throw newInterruptedException();

}int s =state;if (s >COMPLETING) {if (q != null)

q.thread= null;returns;

}else if (s == COMPLETING) //cannot time out yet

Thread.yield();else if (q == null)

q= newWaitNode();else if (!queued)

queued= UNSAFE.compareAndSwapObject(this, waitersOffset,

q.next=waiters, q);else if(timed) {

nanos= deadline -System.nanoTime();if (nanos <= 0L) {

removeWaiter(q);returnstate;

}

LockSupport.parkNanos(this, nanos);

}elseLockSupport.park(this);

}

}

一屏截图不完整,主要截图引起阻塞的判断条件:

376c36fd74ef19f01672ca821b29314c.png

83c90c71c6d439a66b5a5ed1b1b2abf1.png

如果给定的时间是非0(负数)或者给定的时间(正数, 时间单位时毫秒)已经过去了(0的时候会一直阻塞着)

此处因为网络或者其他原因,导致主线程调用future.get()方法时,任务子线程还没有从对接的第三方获取到数据,致使子线程挂起(等待唤醒),从而一直消耗线程池中的资源。

建议修改方案:去掉多线程操作;或者调用future.get(long timeout, TimeUnit unit)方法;

因为当任务正常结束或者异常时,都会调用finishCompletion去唤醒等待线程。

e3eab18b01455619e717e98c450efc06.png

查看官方文档,寻找park方法:

cec45ef67f1cd52fbe649eb5404dff97.png

字面理解park,就算占住,停车的时候不就把这个车位给占住了么?起这个名字还是很形象的。unpark,占住的反义词,就是释放。把车从车位上开走。

翻译一下:

park:阻塞当前线程,(1)当配对的unpark发生或者(2)配对的unpark已经发生或者线程被中断时恢复(unpark先行,再执行park)。 (3)当absolute是false时,如果给定的时间是非0(负数)或者给定的时间(正数, 时间单位时毫秒)已经过去了(0的时候会一直阻塞着)。(4)当Absolute是true时,如果给定的时间(时间单位是纳秒)过去了或者伪造的(在我理解是参数不合法时)线程会恢复中断。这个操作是不安全的,所以在其他调用会很奇怪(奇怪?反正就是用的时候要小心)

unpark:当指定线程被park命令阻塞时unpark命令可以恢复阻塞。在park命令没有被先调用过的时候,调用unpark,线程仍然不被阻塞。

参考文章:

java.util.concurrent.locks.LockSupport类详解:https://my.oschina.net/readjava/blog/282882

futureTask:http://www.cnblogs.com/maypattis/p/5827671.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值