假设我有一些类似于下面的数据存储在一个数组(2D)中。我允许多个用户同时更新它,我想在窗体上实时查看它,或者我可以做任何事情来查看实时更新。
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
26 27 28 29 30
31 32 33 34 35
有人能帮我用Java完成上述任务吗?如果有一种好的方法可以用另一种语言(如Python)实现,我也会很感激。
您必须在保存用户更改的方法或块上使用"synchronized"语句。它只允许一个用户执行整个同步块,直到它完成,从而控制对代码的访问。
这里有一个关于这个问题的文档链接和一些例子。
https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
我假设:
- 您可以接受刷新率是以几十毫秒为单位的预定义值
- 用户可以同时覆盖彼此,更新也可以丢失
- 您并不是真的有兴趣从最终使用的解决方案中挤出每一盎司的性能
- 在不了解这些技术如何在内部工作并对其进行修改以适应新需求的情况下,您不会将此处提供的技术用于不同的用例
话虽如此,您可以简单地使用int
元素的单个共享数组和跟踪其修订的单个共享AtomicLong
。然后,您可以允许每个并发用户对数组进行更新,只需确保AtomicLong
在用户的每次更新时递增即可。
您可以让UI线程通过首先读取AtomicLong
,然后读取数组内容来定期检查共享数据——周期的长度将由您想要保持的帧速率决定,但我认为30毫秒应该足够了。
由于发生在AtomicLong
的写入和读取之间的边缘之前,因此可以保证看到正在更新的线程内容。请注意,如果要使用long
的数组,则需要确保对每个数组元素的写入都是原子的。
以下是一些伪代码对原理的快速说明:
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;
public class Playground {
private static AtomicLong REVISION = new AtomicLong(0);
private static int[] ARR = new int[10];
private static final int NUM_THREADS = 100;
private static final int NUM_UPDATES_PER_THREAD = 100;
public static void main(String[] args) {
new Thread(() -> {
int totalRevs = NUM_THREADS * NUM_UPDATES_PER_THREAD;
while (REVISION.get() < totalRevs) {
System.out.println(Arrays.toString(ARR));
try {
Thread.sleep(50);
} catch (Exception e) {}
}
}).start();
for (int i = 0; i < NUM_THREADS; ++i) {
final int iCopy = i;
new Thread(() -> {
for (int j = 0; j < NUM_UPDATES_PER_THREAD; ++j) {
Random rnd = new Random();
int sleepTime = rnd.nextInt(100);
try {
Thread.sleep(sleepTime);
} catch (Exception e) {}
int index = rnd.nextInt(10);
int value = rnd.nextInt();
ARR[index] = value;
REVISION.incrementAndGet();
}
}).start();
}
}
}