java - Java8;在一个线程上使用睡眠时间,但有多个可调用对象
问题描述
在标准 java8 中是否可以同时在单个线程上执行多个可调用对象?
即当一个可调用对象休眠时,开始处理其他可调用对象。
我目前的实验不起作用:
ExecutorService executor = Executors.newSingleThreadExecutor();
List<Future> fs = new ArrayList<>();
for (int i = 0; i < 2; i++) {
final int nr = i;
fs.add(executor.submit(() -> {
System.out.println("callable-" + nr + "-start");
try { Thread.sleep(10_000); } catch (InterruptedException e) { }
System.out.println("callable-" + nr + "-end");
return nr;
}));
}
try { executor.awaitTermination(5, TimeUnit.SECONDS); } catch (InterruptedException e) { }
结果是:
callable-0-start
callable-0-end
callable-1-start
callable-1-end
我希望有:
callable-0-start
callable-1-start
callable-0-end
callable-1-end
笔记:
- 我有点期待答案:“不,这是不可能的。这不是线程的工作方式。一旦将线程分配给某些可执行代码,它就会运行直到完成、异常或取消。在可调用/可运行之间不能进行中途切换。
Thread.sleep
只有允许其他线程在 CPU/核心上运行。” (明确的确认会让我放心) - 自然,这是“玩具”的例子。
- 这是关于理解,而不是我遇到的一些具体问题。
解决方案
您尝试做的是模拟旧 Java 版本中已弃用的功能。那时可以停止、暂停或恢复Thread
. 但是来自的javadoc Thread.stop
:
这种方法本质上是不安全的。使用 Thread.stop 停止线程会导致它解锁所有已锁定的监视器(这是未经检查的 ThreadDeath 异常沿堆栈传播的自然结果)。如果以前受这些监视器保护的任何对象处于不一致状态,则损坏的对象将对其他线程可见,从而可能导致任意行为。停止的许多用法应该由简单地修改一些变量以指示目标线程应该停止运行的代码替换。目标线程应该定期检查这个变量,如果变量指示它要停止运行,则以有序的方式从它的run方法返回。如果目标线程等待很长时间(例如在条件变量上),则应使用中断方法来中断等待。
如本报告所述,做你想做的事的风险是至关重要的,因此这种行为已被弃用。
我建议,与其试图从外部强制正在运行的线程进入某种停止位置,不如考虑一个允许您正确打包代码段的 ThreadPool API,以便可以从线程,后来又恢复了。例如 create Ticket
,这将是一个基本作业,一个线程总是在开始另一个线程之前完成它,一个TicketChain
顺序连接票证并存储状态。然后制作一个处理程序的处理程序,一张一张地处理票证。如果当前无法完成票证(例如,因为并非所有数据都存在,或者无法获取某些锁),线程可以跳过它,直到稍后的时间点,当所述条件可能为真时。
推荐阅读
- c++ - C++:如何安全地释放堆分配的向量数组?
- ios - 在Objective-C中覆盖.h文件中的静态常量int?
- keras - Keras:如何实现 fcn 结构?
- javascript - JavaScript Bind (this) 不访问类
- curl - 如何使用 LINE Notify 发送多张图片
- javascript - useState 似乎无法正确映射数组
- c++ - 如何访问 std::sub_match 中的正则表达式搜索结果?
- django - 更新 Web 应用程序的最佳工作流程是什么
- python - 什么是 tensorflow.python.ops
- vue.js - 更新缓存 vue-apollo 后缺少字段