做一个小练习记录一个阻塞方法引起的任务无法结束。
场景如下:一个生成质素的类,多个线程调用这个类生成一系列质素。
质素生成类:
public class PrimeGeneratorForeverRun implements
Callable<BlockingQueue<BigInteger>> {
private final BlockingQueue<BigInteger> primes = new ArrayBlockingQueue<BigInteger>(
5);//使用阻塞队列来存储已经生成的质素
private volatile boolean cancelled = false;//退出条件
private static BigInteger b = BigInteger.ONE;
@Override
public BlockingQueue<BigInteger> call() throws Exception {
System.out.println("Begin Time: " + new Date());
while (!cancelled) {
TimeUnit.SECONDS.sleep(1);
synchronized (this) {
b = b.nextProbablePrime();
primes.put(b);
}
}
System.out.println("End Time: " + new Date());
return primes;
}
public void cancel() {//当外部调用这个方法时,将时call中的while循环退出
cancelled = true;
}
}
测试类:
public class PrimeGeneratorForeverRunTest {
/**
* @param args
*/
public static void main(String[] args) {
PrimeGeneratorForeverRun primeGenerator = new PrimeGeneratorForeverRun();//定义一个单例的质素生成器
ExecutorService service = Executors.newFixedThreadPool(2);//定义线程池的大小为2
Future<BlockingQueue<BigInteger>> result1 = service.submit(primeGenerator);//提交任务
Future<BlockingQueue<BigInteger>> result2 = service.submit(primeGenerator);
try {
TimeUnit.SECONDS.sleep(10);//守护线程沉睡10秒,目的是向在10秒内让任务1,2不停的生成质素
} catch (Exception e) {
e.printStackTrace();
} finally {
primeGenerator.cancel();//停止生成质素
service.shutdown();//关闭线程池,这里使用平滑关闭,目的是不强制退出任何线程
try {
BlockingQueue<BigInteger> list = result1.get();//获取第一个任务生成的所有质素
for (BigInteger bigInteger : list) {
System.out.print(bigInteger + ",");
}
System.out.println();
list = result2.get();
for (BigInteger bigInteger : list) {//获取第二个任务生成的所有质素
System.out.print(bigInteger + ",");
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
运行测试类,程序死掉了,一直在运行,查看JVM线程栈信息:
Full thread dump Java HotSpot(TM) Server VM (17.0-b16 mixed mode):
"Attach Listener" daemon prio=10 tid=0x08e7ec00 nid=0x4392 waiting on condition [0x00000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"pool-1-thread-2" prio=10 tid=0x08e70400 nid=0x4369 waiting on condition [0x7b629000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0xa285ddf0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:158)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1987)
at java.util.concurrent.ArrayBlockingQueue.put(ArrayBlockingQueue.java:252)
at org.victorzhzh.concurrency.PrimeGeneratorForeverRun.call(PrimeGeneratorForeverRun.java:24)
- locked <0xa285db78> (a org.victorzhzh.concurrency.PrimeGeneratorForeverRun)
at org.victorzhzh.concurrency.PrimeGeneratorForeverRun.call(PrimeGeneratorForeverRun.java:1)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
Locked ownable synchronizers:
- <0xa285e710> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
"pool-1-thread-1" prio=10 tid=0x08e6cc00 nid=0x4368 waiting for monitor entry [0x7b87a000]
java.lang.Thread.State: BLOCKED (on object monitor)
at org.victorzhzh.concurrency.PrimeGeneratorForeverRun.call(PrimeGeneratorForeverRun.java:23)
- waiting to lock <0xa285db78> (a org.victorzhzh.concurrency.PrimeGeneratorForeverRun)
at org.victorzhzh.concurrency.PrimeGeneratorForeverRun.call(PrimeGeneratorForeverRun.java:1)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
Locked ownable synchronizers:
- <0xa285e520> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
"Low Memory Detector" daemon prio=10 tid=0x08e57400 nid=0x4366 runnable [0x00000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"CompilerThread1" daemon prio=10 tid=0x08e54000 nid=0x4365 waiting on condition [0x00000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"CompilerThread0" daemon prio=10 tid=0x08e52000 nid=0x4364 waiting on condition [0x00000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Signal Dispatcher" daemon prio=10 tid=0x08e50400 nid=0x4363 runnable [0x00000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Finalizer" daemon prio=10 tid=0x08e3dc00 nid=0x4362 in Object.wait() [0x7be83000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0xa2820b10> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
- locked <0xa2820b10> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)
Locked ownable synchronizers:
- None
"Reference Handler" daemon prio=10 tid=0x08e3c400 nid=0x4361 in Object.wait() [0x7bed4000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0xa2820a18> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:485)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
- locked <0xa2820a18> (a java.lang.ref.Reference$Lock)
Locked ownable synchronizers:
- None
"main" prio=10 tid=0x08db0400 nid=0x435d waiting on condition [0xb6b1a000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0xa285e4c0> (a java.util.concurrent.FutureTask$Sync)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:158)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:811)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:969)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1281)
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:218)
at java.util.concurrent.FutureTask.get(FutureTask.java:83)
at org.victorzhzh.concurrency.PrimeGeneratorForeverRunTest.main(PrimeGeneratorForeverRunTest.java:30)
Locked ownable synchronizers:
- None
"VM Thread" prio=10 tid=0x08e39800 nid=0x4360 runnable
"GC task thread#0 (ParallelGC)" prio=10 tid=0x08db7800 nid=0x435e runnable
"GC task thread#1 (ParallelGC)" prio=10 tid=0x08db9000 nid=0x435f runnable
"VM Periodic Task Thread" prio=10 tid=0x08e59000 nid=0x4367 waiting on condition
JNI global references: 855
主要看,如下信息:
"pool-1-thread-2" prio=10 tid=0x08e70400 nid=0x4369 waiting on condition [0x7b629000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0xa285ddf0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:158)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1987)
at java.util.concurrent.ArrayBlockingQueue.put(ArrayBlockingQueue.java:252)
at org.victorzhzh.concurrency.PrimeGeneratorForeverRun.call(PrimeGeneratorForeverRun.java:24)
- locked <0xa285db78> (a org.victorzhzh.concurrency.PrimeGeneratorForeverRun)
at org.victorzhzh.concurrency.PrimeGeneratorForeverRun.call(PrimeGeneratorForeverRun.java:1)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
Locked ownable synchronizers:
- <0xa285e710> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
"pool-1-thread-1" prio=10 tid=0x08e6cc00 nid=0x4368 waiting for monitor entry [0x7b87a000]
java.lang.Thread.State: BLOCKED (on object monitor)
at org.victorzhzh.concurrency.PrimeGeneratorForeverRun.call(PrimeGeneratorForeverRun.java:23)
- waiting to lock <0xa285db78> (a org.victorzhzh.concurrency.PrimeGeneratorForeverRun)
at org.victorzhzh.concurrency.PrimeGeneratorForeverRun.call(PrimeGeneratorForeverRun.java:1)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
Locked ownable synchronizers:
- <0xa285e520> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
由于阻塞队列满了,所以pool-1-thread-2进入了等待状态,而由于pool-1-thread-2锁住了PrimeGeneratorForeverRun对象,所以pool-1-thread-1进入了阻塞状态,因此即使这时我们调用了PrimeGeneratorForeverRun.cancel()方法,也无法停止生成质素的循环,因为线程一个处于等待状态,一个处于阻塞状态,都不能取校验cancelled标志位,所以线程只能保持源状态继续,而守护线程中我们用的是shutdown,只要有线程在运行那么线程池就不会关闭,因此程序将一直运行。
解决方法很容易了,这里就不再列出。
分享到:
相关推荐
进程管理 执行 唤醒 阻塞 结束
基于thinkphp5框架的定时任务行为扩展
阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池...
基于xxl-job改造,支持1.6jdk。改分布式任务调度特性如下: 1、简单:支持通过Web页面对任务...15、任务依赖:支持配置子任务依赖,当父任务执行结束且执行成功后将会主动触发一次子任务的执行, 多个子任务用逗号分隔;
本文为大家介绍交换机数据阻塞引起网络故障案例分析。
C++串口通信类。 可以方便的进行串口通信,如果需要用串口可以试用一下哈。包括阻塞与非阻塞方法。
quartz定时任务使用例子大全,这里面介绍了三种使用quartz定时任务的方式,第一种方式是完全使用代码写死的调用方式,第二种使用的是从数据库读取任务配置信息的调用方式,第三种是使用从数据库读取任务配置,生成...
这是配合我的一篇文章的代码,配合使用效果更佳。欢迎下载学习!如有错误,欢迎批评指正!欢迎交流学习!您的鼓励是我创作的动力!
使用里面的 _sock 方法非阻塞运行 如果进程死掉了 在触发时 会根据 cron.log 的文件时间 判断超过运行间隔 时间+10秒 重新继续运行 ,cron-run 保证进程只有1个。要停掉定时任务 修改cron-switch文件不存在即可。重...
针对多通道并行传输中的接收缓存阻塞问题,分析了引起接收缓存阻塞的原因,提出一种改进的缓解接收缓存阻塞的数据包调度方法,综合考虑通道的带宽、时延和丢包率,引入通道质量的评价函数,优化多通道之间的数据包...
前端开发中,我们会会经常使用定时器setinterval setTimeout等,但当我们离开页面时,定时器会被阻塞,导致我们再回到页面的时候定时任务会混乱运行,为些我的解决方案写了个简单demo,希望对你有所帮助
传统的单片机系统监控程序通常是基于单任务机制的.这种机制具有简单直观、编程容易的优点 .然而由于程序只能按单一的线索顺序执行,缺乏灵活性,在复杂系统中难以胜任.为了在更广泛的领域应用单片机系统,必须对传统的...
这是我做的操作系统实验,完成了进程调度的所有任务,显示出了一个作业被调度的所有状态,准备,就绪运行,阻塞挂起,包括进程运行结束后的打印。其中挂起为手动挂起。并用图像表示内存分配
网络游戏-分组网络中表示几种不同阻塞原因的阻塞通知方法及设备.zip
导致问题:getView需要执行很多个异步任务造成堵塞(下载不看的图片造成用户流量损失),且无法再第一时间展示用户想看的界面。 个人做了小demo 可以再ListView滚动结束后 只加载当前用户可视区的图片。减少堵塞...
同步异步阻塞非阻塞
2、 定义进程状态转换方式:进程的状态转换是由进程内部操作或操作系统的控制引起,由于无法实现这些功能,学生可以采用随机数方法或键盘控制方法模拟,并实现对应的控制程序。随机方法指产生1-6的随机数,分别代表...
socket阻塞与非阻塞
C++ Socket编程示例; 阻塞和非阻塞,涉及多线程编程,以及定时清除服务器连接资源;
一种构建无阻塞多级互连网络的方法,冯勇华,罗风光,提出一种构建无阻塞多级互连网络的一般方法。与Clos、Benes及Waksman等网络的递归构建方法不同,该方法将多级互连网络分为置换网络和��