我有一个关于线程池的问题。
这是我的情况:
从后端服务的某个地方,我们会收到pdf文件列表。
首先需要将这些pdf页面一个一个地转换为.bmp文件。
转换后,需要打印这些bmp。
问题是转换和打印任务都需要一段时间才能完成,我想使此过程更快,因为否则可能要花一些时间才能有人看到打印机中有东西出来。
我考虑过的解决方案是创建2个ThreadPool:一个用于转换,另一个用于打印。
这些就是我的线程池:
ExecutorService convertPool = Executors.newFixedThreadPool(10);
ExecutorService printPool = Executors.newSingleThreadExecutor();
具有10个线程的convertPool
,可将pdf页面转换为bmp。
完成此操作后,创建的bmp将发送到printPool。这是一个单线程,因为始终只能进行一次打印。
但现在我的问题是:
因此convertPool已完成了第一个pdf的工作,并将所有将来的任务发送到PrintPool进行打印。
但是当printPool繁忙时,我希望convertPool
已经从第二个pdf开始。这样,当PrintPool完成后,就可以从第一个pdf打印bmp了,因为它已经创建,因此可以立即开始处理第二个pdf的bmp打印。
但是如何设置这种机制?有人可以帮我吗?
谢谢!
答案 0 :(得分:0)
现在您可以使用许可范围有限的信号量,例如(10),并且任何可调用的信号量
结束执行,它可以释放可运行对象将要使用的许可证
尝试事先获取并保持在阻止状态,因为没有可用状态。
注意:每个可处理Callable的PDF处理都将在其开始执行时获得许可。
您的可运行物品可以在获取任何许可证之前尝试获取许可证
返回Done()
状态为true并可以释放
允许在迭代的末尾。
shutdownNow()
终止执行程序,从而终止可运行程序。 希望有帮助!
答案 1 :(得分:0)
您处在正确的轨道上。您可以根据需要向转换器池提交任意数量的转换任务。它将尽快执行它们,并将那些还不能由线程服务的队列排队。每个转换任务完成后,它可以将自己提交给打印池,该打印池还将根据需要将任务排队。这是我的意思的基本骨架:
class Conversion implements Runnable {
Consumer<Conversion> onCompletion;
Conversion(Consumer<Conversion> onCompletion) {
this.onCompletion = onCompletion;
}
@Override
public void run() {
// ... conversion code. You could Thread.sleep()
// here to simulate the conversion work taking up
// some time.
// (now we're done converting)
onCompletion.accept(this);
}
}
class Print implements Runnable {
Print(Conversion c) {
// ...
}
// ...run() method, etc.
}
// Example of submitting a conversion task to the executor
convertPool.submit(new Conversion(c -> printPool.submit(new Print(c))));