I've been puzzling over a good implementation for this for a while. I have a program that does a long-running I/O operation (downloading a file) and a long-running CPU operation (parsing its contents). To improve efficiency, I wanted to have one thread pool perform the I/O section and have it pass tasks to another thread pool that performs the CPU section. That way, it's unlikely that all threads will be stuck either hogging the I/O or hogging the CPU. Depending on the file, one operation will likely take longer than the other.
What's the best way to perform a hand-off between thread pools? Assuming I'm using Java with two ExecutorServices, like so:
int threads = Runtime.getRuntime().availableProcessors();
ExecutorService ioService = Executors.newFixedThreadPool(threads);
ExecutorService cpuService = Executors.newFixedThreadPool(threads);
public BigFile ioTask(){
return Connection.downloadBigFile();
}
public void cpuTask(BigFile bigFile){
processBigFile(bigFile);
}
What's the best way to have a task running under ioService
to add a task to cpuService
while passing data into it?
What I've considered:
- Submit a
Runnable
tocpuService
that executes aCallable
inioService
. BlockscpuService
while running theCallable
. - Submit a
Runnable
toioService
that executes aRunnable
incpuService
. BlocksioService
while running the secondRunnable
. - Create a
Runnable
implementation that has anIOTaskResult
constructor, allowingioService
runnables to submit these implementations to thecpuService
. Turns a reusable processing object into a consumable process object, which adds more overhead. - Add a method to generate a
Runnable
to the CPU task processor. This feels like a workaround and kind of "hack-y", considering I have a method I can call and theRunnable
just wraps the method and fills in the parameters for me.
Is there a good way of handling this? I'd love to hear some thoughts.