In Goetz\'s \"Java Concurrency in Practice\", in a footnote on page 101, he writes \"For computational problems like this that do not I/O and access no shared data, Ncpu or
If you are using synchronous I/O, then you should have one thread for every simultaneous I/O request your machine can handle. In the case of a single spindle single hard disk, that's 1 (you can either read or write but not both simultaneuosly). For a disk that can handle many I/O requests simultaneously, that would be however many requests it can handle simultaneously.
In other words, this is not bounded by the CPU count, as I/O does not really hit the CPU beyond submitting requests and waiting. See here for a better explanation.
There's a whole other can of worms with how many I/O requests you should have in flight at any given time.