我有一个 ThreadPoolTaskExecutor
,当我创建一个实现 Runnable
的 Process
时,我通过以下方式运行它:executor.execute(process )
。
现在,在调用 execute
之前,我想检查 Process
对象中的一个字段,并将其与所有其他 当前运行 进程进行比较,由我的 ThreadPoolTaskExecutor
。我如何做到这一点,而不产生并发问题?
代码:
public class MyApp {
ThreadPoolTaskExecutor executor;
//...
public void runProcesses {
Process firstone = new Process(1);
Process nextOne = new Process(1);
// iterate through all processes started via executor and currently running,
// verify if there is any process.getX() == 1, if not run it
executor.execute(firstone );
//wait till firstone will end becouse have the same value of X
executor.execute(nextOne); // this cant be perform until the first one will end
}
}
public class Process {
private int x;
//...
public Process (int x){
this.x = x;
}
public int getX(){
return this.x;
}
}
我正在考虑创建简单的 Set
流程启动并向其中添加新流程。但是我有问题如何确定它是否仍在运行并在完成后将其从集合中删除。所以现在我正在考虑遍历正在运行的线程,但完全不知道怎么做。
最佳答案
我认为您最初的想法非常好,无需太多代码即可实现。
它需要一些修补才能将“是一个 Runnable
对于这个值已经运行”从“执行这个 Runnable
” 中分离出来,但这里有一个粗略的例子,没有考虑到这一点:
- 实现
equals()
和hashCode()
在Process
,以便实例可以安全地用于无序集和映射。 - 创建
ConcurrentMap<Process, Boolean>
- 您不会使用
Collections.newSetFromMap(new ConcurrentHashMap<Process, Boolean>)
因为你想使用 map 的putIfAbsent()
方法。
- 您不会使用
- 尝试使用
putIfAbsent()
添加进去每个Process
如果返回值不是null
,您将提交并保释.- 非
null
返回值意味着已经有一个等价的Process
在 map 中(因此正在处理中)。 - 简单且不是很干净的解决方案是在每个
Process
中注入(inject)对 map 的引用。实例并有putIfAbsent(this, true)
作为你在run()
中做的第一件事方法。
- 非
- 从中删除每个
Process
已经完成处理。- 简单且不是很干净的解决方案是在每个
Process
中注入(inject)对 map 的引用。实例并有remove(this)
作为你在run()
中做的最后一件事方法。 - 其他解决方案可以有
Process
实现Callable
并返回其唯一值作为结果,以便可以将其从 map 中删除,或使用CompletableFuture
及其thenAccept()
回调。
- 简单且不是很干净的解决方案是在每个
Here's一个示例,说明了上述简单且不是很干净的解决方案(代码太长,无法直接粘贴到此处)。
关于java - 遍历通过 ThreadPoolTaskExecutor 运行的线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36642539/