我正在使用第三方库对7张牌扑克牌进行手牌评估。此库中的方法evaluate
被声明为public static,我相信它会改变类中的一些全局静态数组。我遇到的问题是,当我正在进行大约10米枚举的枚举算法时,我想并行化它,因此我创建了FutureTasks,每个都评估了10米评估的一小部分。我得到的错误是:
java.util.concurrent.ExecutionException: java.lang.ArrayIndexOutOfBoundsException: -2147483648
at java.util.concurrent.FutureTask$Sync.innerGet(Unknown Source)
at java.util.concurrent.FutureTask.get(Unknown Source)
在尝试检索因抛出异常而中止的任务结果时,会从Google搜索中收集到的内容。
是否有某种方法可以使这个静态方法线程安全,就像每个线程制作自己正在编辑的全局静态数组的副本一样?
由于
答案 0 :(得分:3)
你可以在每个线程的单独ClassLoader
中加载库,以确保每个类都有自己的类集,因此也有自己的一组静态变量。
如果这样做,您必须小心确保这些类加载器的父类加载器无法访问该库。
答案 1 :(得分:2)
如果您可以修改代码,则可以创建静态变量thread local,但听起来您不能修改代码的这一部分。更多关于thread local storage(维基百科)
答案 2 :(得分:1)
使用evaluate方法
上的同步方法修饰为库创建单例实例包装器public final class SynchronizedHandEvaluator {
private static final SynchronizedHandEvaluator INSTANCE = new SynchronizedHandEvaluator();
public static final getInstance() {
return INSTANCE;
}
private SynchronizedHandEvaluator() { }
public synchronized int evaluate(Card[] hand) {
return ExternalLibrary.evaluate(hand);
}
}
// then just use the wrapper as you would expect
int result = SynchronizedHandEvaluator.getInstance().evaluate(hand);
答案 3 :(得分:0)
您是否安全地在阵列上操作?你能更好地解释你的代码结构吗?你是如何划分工作的?为什么算法需要修改全局数组?
无论如何,使用ForkJoin或CyclicBarrier / Phaser来分割工作会更有意义吗?
答案 4 :(得分:0)
如果有多个线程使用共享状态(全局静态数组)访问某个方法,则需要确保以线程安全的方式访问它们。
这意味着当您从这些数组读取时以及写入数据时都需要同步/锁定它们。
听起来,只是来自你的堆栈跟踪,你不是。
如果可能,我建议最小化或消除线程之间共享的状态量。
答案 5 :(得分:0)
您无法使其成为线程安全的,但您可以同步对库的访问:
static Object globalLock = new Object();
synchronize (globalLock) {
evaluate();
}
这意味着,当然,一次只有一个线程可以执行此方法。因此,如果您的程序在该方法上花费了大量时间,那么它对您没有帮助。
或者,您可以使实例在单独的进程中运行。但是在进程之间建立通信(通过RMI或类似方法)是非常痛苦的。
如果您访问源代码,唯一的另一个选择是重写它。您必须将所有静态字段移动到单个上下文类中,然后确保用于访问静态字段的所有代码都引用了新上下文类的实例。
已经提到的ThreadLocal机制可以帮助您解决这个问题,因为它是一种特殊的引用,它看起来与每个线程不同。这可以使您免于修改方法签名以将实例传递给上下文对象。恕我直言,将上下文传递给方法可能更干净。利用现代IDE的重构功能,这并不难。
答案 6 :(得分:0)
使用ConcurrentLinkedQueue
或Collections#synchronizedList()
代替数组。它的访问是内部同步的。
答案 7 :(得分:0)
有数百万只手要评估,现在看Java Distributed Computing永远不会太早。
当您考虑另一个good suggestion时,您可以将评估程序包装在一个简单的单线程服务器中,并在资源允许的情况下启动尽可能多的JVM。
最后,考虑编写自己的评估者;你可以测试你现有的,你的可能会更好!