Java 使用ExecutorService和BlockingQueue可运行锁定(驻车)
注意:我了解网站的规则,但我无法将所有代码(复杂/大型代码)放入网站 我放了一个不同的(所有真正的代码都太多了,你在这里不需要)代码,但复制了问题(主类是Java 使用ExecutorService和BlockingQueue可运行锁定(驻车),java,executorservice,blockingqueue,linkedblockingqueue,Java,Executorservice,Blockingqueue,Linkedblockingqueue,注意:我了解网站的规则,但我无法将所有代码(复杂/大型代码)放入网站 我放了一个不同的(所有真正的代码都太多了,你在这里不需要)代码,但复制了问题(主类是joseluisbz.mock.support.testoptimizedsp,切换类是joseluisbz.mock.support.runnable.ProcessorDSP)就像视频一样 请不要向我推荐用于此代码的其他jar或外部库 我希望我能说得更具体些,但我不知道该提取和展示什么部分。 在你结束这个问题之前:显然,如果有人告诉我去哪里
joseluisbz.mock.support.testoptimizedsp
,切换类是joseluisbz.mock.support.runnable.ProcessorDSP
)就像视频一样
请不要向我推荐用于此代码的其他jar或外部库
我希望我能说得更具体些,但我不知道该提取和展示什么部分。
在你结束这个问题之前:显然,如果有人告诉我去哪里看(技术细节),我愿意改进我的问题
我做了一个演讲以表明我的观点
甚至为了阐述这个问题,我还画了一张图表来说明情况
我的程序有一个JTree
,显示工作者之间的关系
我使用ExecutorService ExecutorService=Executors.newCachedThreadPool()在控制生命周期的线程之间建立了一个图表交互代码>和列表首先,设置线程名称的方式是错误的。您可以使用以下模式:
public class Test
{
public static class Task implements Runnable
{
public Task()
{
Thread.currentThread().setName("Task");
}
@Override
public void run()
{
System.out.println("Task: "+Thread.currentThread().getName());
}
}
public static void main(String[] args)
{
new Thread(new Task()).start();
System.out.println("Main: "+Thread.currentThread().getName());
}
}
这会产生(不期望的)结果:
这是不正确的,因为在任务
构造函数中,线程尚未启动,因此您正在更改调用线程的名称,而不是生成线程的名称。您应该在run()
方法中设置名称
因此,屏幕截图中的线程名称是错误的
现在才是真正的问题。在中,您有以下行:
List<ChunkDTO> listDelayedChunkDTO = mapListDelayedChunkDTO.putIfAbsent(chunkDTO.getPitch(), new ArrayList<>());
这意味着您将null
作为listdayedchunkdto
参数传递。因此,当这一行在ProcessorDSP
中执行时:
if (listDelayedChunkDTO.size() > 2) {
它抛出一个NullPointerException
,runnable停止。我不太清楚你问题的背景。你能创建一个吗?@JacobG。现在,我上传了一个视频来显示这个问题,因为我不知道原因,我不知道为了重复ant在这里提出的问题提取了什么代码。(我需要等待1个小时)我可以理解,如果您使用的是集合#synchronizedMap
,它为什么会阻塞,但如果您只是使用HashMap
,则不会阻塞。使用新建HashMap(),结果是相同的
或集合.synchronizedMap(新的HashMap())代码>每个Runnable都是这样启动的:listFuture().add(executorService().submit(this));在其构造函数中。
听起来像是“泄漏”引用,请尽量避免这种情况。jfyi:我发现您在中对putIfAbsent()
的使用也不正确。请注意,即使条目已经存在,也始终会计算第二个参数!这意味着您将始终创建一个WorkerDSPPitchIncrement()
对象,这显然是不可取的。我理解,根据实现,它不应返回null<代码>V=map.get(键);如果(v==null){v=map.put(key,value);}返回v代码>我改为V=map.get(键);如果(v==null){map.put(key,value);v=map.get(key);}返回v
@joseluisbz返回“如果键没有映射,则返回null”,因此这是预期的行为。您认为使用List listdayedchunkdto=new ArrayList()更好吗
或列表listDelayedChunkDTO=Collections.synchronizedList(新的ArrayList())代码>在WorkerDSPDecrement、WorkerDSPFilter、WorkerDSPPitchIncrement和Map-mapWorkerDSPPitchIncrement=new HashMap()
或映射mapWorkerDSPPitchIncrement=Collections.synchronizedMap(新HashMap())代码>输入WorkerDSP@joseluisbz这取决于集合是否被并发访问。如果只有一个线程访问它们,那么就没有理由使它们同步。
Main: Task
Task: Thread-0
List<ChunkDTO> listDelayedChunkDTO = mapListDelayedChunkDTO.putIfAbsent(chunkDTO.getPitch(), new ArrayList<>());
ProcessorDSP processorDSP = new ProcessorDSP(controlDSP, upNodeDSP, null,
dHnCoefficients, chunkDTO, listDelayedChunkDTO, Arrays.asList(parent.getParentBlockingQueue()));
if (listDelayedChunkDTO.size() > 2) {