Since each loop you increment position by count+1, and you make a Transfer with `(fis,fos,position,position+count), your code will create Transfer objects as follows:
new Transfer(fis, fos, 0,count)
new Transfer(fis, fos, count+1, 2count+1)
new Transfer(fis, fos, 2count+2, 3count+2)
new Transfer(fis, fos, 3count+3, 4count+3)
...
So although you'll create filesize / count
Transfer classes, you're asking to transfer (count + 1) * (1 + 2 + 3 + ...)
bytes in total.
Furthermore, I don't think FileChannel.TransferTo()
works the way you think it does. position
specifies the position in the source file where you start reading. It doesn't specify the position to which you write in the destination channel. So even when you get the sizes right, you'll end up with the right size output file, but the contents will be jumbled up in whatever order the threads happen to write them.
You could call outChannel.position()
to skip to the right place. It's not clear to me what kind of chaos might happen as multiple threads extend the filesize in this way.
It's fine to experiment, and I encourage you to try this out and benchmark. However the comments are correct that the approach is misguided. There is only one disk, backed by just one filesystem buffer, and having multiple threads fight over it won't make it work faster -- and may make it slower.
You're unlikely to improve on:
long count = 0;
long size = src.size();
while(count < size) {
count += src.transferTo(count, size - count, dest);
}
Do also note that it's very difficult to make judgements about the performance of file operations, since the filesystem will be caching both reads and writes, so an awful lot of what you do will just be super-cheap operations on RAM.
Also note that, at least when benchmarking, you're going to need to join()
with all the threads you've started, before considering the copy complete.