我理解Java的AsynchronousFileChannel是异步api(不会阻塞调用线程),并且可以使用系统线程池中的线程。
我的问题是:AsynchronousFileChannel操作的线程比是1:1吗?
换句话说,如果循环使用AsynchronousFileChannel来读取100个文件,它会使用100个线程来执行此操作,还是只使用少量线程(以标准NIO方式)?
答案 0 :(得分:4)
AsynchronousFileChannel
实现(实际上在Linux上使用)是SimpleAsynchronousFileChannelImpl,它基本上提交Runnables
,阻止IO读取+处理结果在同一个线程中(填写一个将来或CompletionHandler
}调用ExecutorService
,其中"sun.nio.ch.internalThreadPoolSize"
作为参数提供给AsynchronousFileChannel::open
,否则使用默认的系统范围(is无界限can be configured缓存线程池,但有一些选项think)。有些WindowsAsynchronousFileChannelImpl表示文件是最好的,因为它们总是可读的#34;或者至少操作系统没有提供任何他们不知道的线索。
在Windows上,使用了一个名为I/O completion ports的单独实现。它在Windows Vista / 2008及更高版本(主要版本> =" 6")上运行时使用 aka IOCP,并且通常表现得更像您期望的:默认情况下它使用1个线程进行调度读取结果(可由ExecutorService
系统属性配置)和用于处理的缓存线程池。
所以,回答你的问题:如果你不提供自己的AsynchronousFileChannel::open
(比如一个固定的)给CompletionHandlers
,那么它将是1 :1个关系,所以100个文件将有100个线程;除了非古老的Windows,默认情况下会有1个线程处理I / O但是如果所有结果同时到达(不太可能但仍然)并且你使用TF.class
,那么它们也会在它自己的线程中被调用
编辑:我实现了100个文件的读取并在Linux和Windows上运行(openjdk8)并且1)确认两个实际使用的类(用于删除CompletionHandlers
仍然在命令行中指定它并查看堆栈跟踪),2)确认使用的线程数:在Linux上为100,在Windows上为4,如果完成处理速度很快(如果import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.file.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.*;
public class AsynchFileChannelDemo {
public static final AtomicInteger ai = new AtomicInteger();
public static void main(String[] args) throws IOException, InterruptedException, ExecutionException {
final List<ByteBuffer> bufs = Collections.synchronizedList(new ArrayList<>());
for (int i = 0; i < 100; i++) {
Path p = Paths.get("some" + i + ".txt");
final ByteBuffer buf = ByteBuffer.allocate(1000000);
AsynchronousFileChannel ch = AsynchronousFileChannel.open(p, StandardOpenOption.READ);
ch.read(buf, 0, buf, new CompletionHandler<Integer, ByteBuffer>() {
@Override
public void completed(Integer result, ByteBuffer attachment) {
bufs.add(buf);
// put Thread.sleep(10000) here to make it "long"
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
}
});
}
if (args.length > 100) System.out.println(bufs); // never
System.out.println(ai.get());
}
}
不是,那么它将是相同的如果完成处理很慢,则在Windows上使用100)。虽然很丑,但代码是:
import java.util.concurrent.ThreadFactory;
public class TF implements ThreadFactory {
@Override
public Thread newThread(Runnable r) {
AsynchFileChannelDemo.ai.incrementAndGet();
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
}
和
some0.txt
编译这些内容,将它们放在一个包含100个名为some99.txt
到java -Djava.nio.channels.DefaultThreadPool.threadFactory=TF AsynchFileChannelDemo
的文件的文件夹中,每个文件大小为1Mb,这样读取速度就不会太快,请将其作为
button:focus{
outline:0px;
}
打印的数字是线程工厂创建新线程的次数。