Gil*_*ili 6 java multithreading fork-join forkjoinpool
是否可以配置ForkJoinPool为使用1个执行线程?
我正在执行Random在一个内部调用的代码ForkJoinPool.每次运行时,我都会遇到不同的运行时行为,因此很难调查回归.
我希望代码库提供"调试"和"发布"模式."debug"模式将Random使用固定种子配置,并ForkJoinPool使用单个执行线程."release"模式将使用系统提供的Random种子并使用默认的ForkJoinPool线程数.
我尝试ForkJoinPool使用1的并行性配置,但它使用2个线程(main和第二个工作线程).有任何想法吗?
所以,事实证明我错了.
当您配置ForkJoinPool与parallelism设置为1,只有一个线程执行的任务.该main线程被阻塞ForkJoin.get().它实际上并不执行任何任务.
也就是说,事实证明提供确定性行为真的很棘手.以下是我必须纠正的一些问题:
ForkJoinPool如果工作线程空闲时间足够长,则使用不同的工作线程(具有不同的名称)执行任务.例如,如果主线程在调试断点上挂起,则工作线程将变为空闲并关闭.当我恢复执行时,ForkJoinThread会启动一个具有不同名称的新工作线程.为了解决这个问题,我必须提供一个自定义ForkJoinWorkerThreadFactory实现,null如果ForkJoinPool已经有一个实时工作者则返回(这可以防止池创建多个工作者).Random即使工作线程关闭并再次返回,我也确保我的代码返回相同的实例.HashMap或HashSet导致元素在每次运行时以不同的顺序获取随机数.我通过使用LinkedHashMap和更正了这个LinkedHashSet.Enum.hashCode().我忘了这引起了什么问题但我通过自己计算hashCode()而不是依赖内置方法来纠正它.这是ForkJoinWorkerThreadFactory的示例实现:
class MyForkJoinWorkerThread extends ForkJoinWorkerThread
{
MyForkJoinWorkerThread(ForkJoinPool pool)
{
super(pool);
// Change thread name after ForkJoinPool.registerWorker() does the same
setName("DETERMINISTIC_WORKER");
}
}
ForkJoinWorkerThreadFactory factory = new ForkJoinWorkerThreadFactory()
{
private WeakReference<Thread> currentWorker = new WeakReference<>(null);
@Override
public synchronized ForkJoinWorkerThread newThread(ForkJoinPool pool)
{
// If the pool already has a live thread, wait for it to shut down.
Thread thread = currentWorker.get();
if (thread != null && thread.isAlive())
{
try
{
thread.join();
}
catch (InterruptedException e)
{
log.error("", e);
}
}
ForkJoinWorkerThread result = new MyForkJoinWorkerThread(pool);
currentWorker = new WeakReference<>(result);
return result;
}
};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1333 次 |
| 最近记录: |