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
RunnabletocpuServicethat executes aCallableinioService. BlockscpuServicewhile running theCallable. - Submit a
RunnabletoioServicethat executes aRunnableincpuService. BlocksioServicewhile running the secondRunnable. - Create a
Runnableimplementation that has anIOTaskResultconstructor, allowingioServicerunnables 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
Runnableto the CPU task processor. This feels like a workaround and kind of "hack-y", considering I have a method I can call and theRunnablejust 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.