我有一堆要求严格的操作可以并行运行,但必须以某种顺序完成。完成后我的意思是将结果写入文件。当然,我可以在所有工作完成后重新排序结果,但我想避免这种情况(特别是因为结果可能太大而无法保存在内存中)。
我使用修改后的ThreadPoolExecutor
并行运行作业,以确保一次只运行有限数量的作业以减少内存消耗。
我的想法是每个作业都会引用前一个作业,在写入结果之前,它将等到上一个作业完成(如果需要)。这似乎是一个简单的同步问题,但由于我没有这种东西的经验,我希望听到一个意见,如果它实际上按预期工作。还有关于内存管理。作业完成后,垃圾收集器应该能够从内存中删除它。
abstract public class WaitingJob extends Job {
/** Job to wait for before we finish this job */
protected WaitingJob previousJob;
/** Job status */
protected boolean finished = false;
public WaitingJob(WaitingJob previousJob) {
this.previousJob = previousJob;
}
@Override
public void run() {
// Perform the actual job (which might decide to wait for the previous one)
runWithWaiting();
// Wake up any job that's waiting for us.
synchronized (this) {
finished = true;
notifyAll();
}
// Release memory (manually, to break the chain).
previousJob = null;
}
/** If the previous job is not finished yet, let's wait for it. */
protected void waitForPreviousJob() throws InterruptedException {
if (previousJob != null) {
synchronized (previousJob) {
while (!previousJob.finished) {
previousJob.wait();
}
}
}
}
/** Perform the job with the possibility to wait on the previous one. */
protected abstract void runWithWaiting();
}
示例工作:
class SampleJob extends WaitingJob {
@Override
protected void runWithWaiting() {
try {
Thread.sleep(1000); // Do heavy work
waitForPreviousJob();
// Write down work
} catch (InterruptedException e) {
}
}
}
我对此进行了几次测试,似乎表现得应该如此,但我不确定是否有任何危险的时刻。
此外,是否有更好的解决方案?
答案 0 :(得分:1)
在我看来,这应该有效并且是一个合理的解决方案。唯一可能的问题是,根据代码的其余部分,所有线程可能会占用正在等待尚未分配线程的作业的作业,从而导致死锁(例如,在池中有四个线程,作业2-5完成并使其线程处于等待状态,而作业1无法获得线程,因为它们全部被占用)。但是,这可能不适用于您的情况。