Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/375.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中用于蜂窝自动化的线程安全高性能矩阵式容器?_Java_Multithreading_Cellular Automata - Fatal编程技术网

Java中用于蜂窝自动化的线程安全高性能矩阵式容器?

Java中用于蜂窝自动化的线程安全高性能矩阵式容器?,java,multithreading,cellular-automata,Java,Multithreading,Cellular Automata,我正在做一个细胞自动机,我正在运行一个类的实例,并为它提供了一个特定的线程。对于新功能,即在模拟继续进行时通过鼠标输入添加活动单元,我必须从主线程访问正在进行模拟的类实例,以修改其名为2D container的ArrayList>“world”,我的Draw类将其用作绘制参考 但是ArrayList不是线程安全的,我会出错。此时,我的“细胞世界”只有50x50,但我想将其大小扩展到10000^2甚至更大。(我会使用四叉树的大小) 所以我的问题是,我应该使用什么样的容器,既可以是线程安全的,也不会

我正在做一个细胞自动机,我正在运行一个类的实例,并为它提供了一个特定的线程。对于新功能,即在模拟继续进行时通过鼠标输入添加活动单元,我必须从主线程访问正在进行模拟的类实例,以修改其名为2D container的ArrayList>“world”,我的Draw类将其用作绘制参考

但是ArrayList不是线程安全的,我会出错。此时,我的“细胞世界”只有50x50,但我想将其大小扩展到10000^2甚至更大。(我会使用四叉树的大小)

所以我的问题是,我应该使用什么样的容器,既可以是线程安全的,也不会以更高的数量级占用所有系统资源,并且与四叉树概念“兼容”

我对多线程不太了解,如果像这样打扰一个重量级线程,我应该放弃这个想法吗?或者我可以暂停线程以评估用户的输入吗?(实际上我尝试过,我让线程进入睡眠状态,同时尝试访问实例,但没有成功。)

我检查了一些threadsafe容器,它们的性能取决于我是迭代它们还是编辑它们的属性等等。有太多的事情要考虑,我真的很感激如果有人能告诉我选择什么方向,
安得烈。

< P>如果你只有两个线程,并且你的自动机线程可以被写来周期性地放弃对关键部分的访问,那么你可能需要考虑一个可重入的锁:


它的语义简单明了,在涉及少量线程时效果最好。

假设在启动过程中,单元格本身只创建一次并添加到矩阵中;问题不在于ArrayList,而在于单元格。这是因为从ArrayList中读取是线程安全的,与读取线程的数量无关;线程不安全的是写入一个单元格的字段,而另一个线程正在读取这些字段


在这种情况下,我建议只对单元本身使用方法,并对单元本身进行同步。这样,在任何时候只有一个线程能够访问单元格的字段。无需同步每个方法,只需同步读写两个线程访问的字段的方法。

您可以使用类似的概念。因此,有两个不同的平面,我们称它们为A和B。每个平面代表整个细胞的“世界”。UI线程能够在屏幕上绘制平面

在第一次迭代中,通过从平面A读取来更新平面B。由于平面A只读取而不写入,而平面B只写入而不读取,因此可以在没有任何锁的情况下进行多线程处理。只需将平面拆分为多个部分,并将每个部分指定给不同的线程。这可以通过使用来动态完成

完成第一次迭代后,将平面B移交给UI线程。同时,您可以开始下一个迭代,现在从平面B读取到平面A。同样,这可以并行完成

一般而言,请遵循以下规则:

  • 在每次迭代中,一个平面是只读的,另一个是只读的
  • UI线程总是引用只读平面进行重绘
  • 单元更新线程具有独立的、不重叠的读写部分
  • 唯一的同步是在每次迭代结束时切换平面
Java拥有优秀的并发工具,可用于以下方面,如
ForkJoinPool
Exchanger
CyclicBarrier


只写平面可以维护一个或多个脏区域,因此UI线程不必一直更新整个UI。但是要聪明-一个脏区域可能是一个瓶颈,因为所有线程都必须在它上面同步

谢谢,它看起来很有希望。您可能应该更详细地解释您收到的“错误”以及“添加活动单元格”的含义(我猜:您正在使用类似于
list.set(i,new LiveCell())
的内容,并收到一个
ConcurrentModificationException
。也许您可以给单元格一个状态,比如
cell.ishead()
,这可以简化事情…)如果像这样的东西:公共同步的void setCells(int a,int b,boolean c){world.get(a).set(b,c);}解决了像ArrayList这样的非线程安全容器的问题,那么人们为什么要使用类似的线程安全容器呢?保存某些对象的数据结构之间存在差异,以及这些物体本身。由于对象只添加到数组列表中一次,因此数组列表不会更改,只会一次又一次地读取。因此,使用多个线程访问它没有问题。当集合本身被修改时,人们会为线程安全的集合而烦恼。例如,如果对象由多个线程从集合中添加或删除,而其他线程从集合中读取。据我所知,这不是您的情况。这是我的情况,两个线程都修改嵌套的ArrayList。通过评估下一次迭代进行的模拟,以及在网格上绘制新单元时用户输入的主线程。