我想编写一个程序,它可以同时写入多个文件;认为通过使用非阻塞模式的一个线程是可能的。但FileChannel不支持非阻塞模式。有人知道为什么吗?为什么Java中的FileChannel不是非阻塞的?
回答
UNIX不支持文件的非阻塞I/O,请参见Non-blocking I/O with regular files。由于Java应该(至少试图)在所有平台上提供相同的行为,因此FileChannel
不实现SelectableChannel
。
但是Java 7将包含一个新的AsynchronousFileChannel
类,该类支持异步文件I/O,这是与非阻塞I/O不同的机制。它的一个实现WindowsAsynchronousFileChannelImpl
受益于Windows上的非阻塞I/O API(请参阅Asynchronous I/O in Windows)。
与此同时,您可以使用多个线程来实现相同的效果。但是这已经在SimpleAsynchronousFileChannelImpl
中实现了,它可以跨所有操作系统使用。
通常只有插座和管道通过select()
机制真正支持非阻塞I/O。
@Trying评论从而:
“AsynchronousFileChannel支持异步I/O而不是无阻塞”。
我认为,异步I/O(例如使用Future
或CompletionHandler
)是非阻塞的I/O的形式。
- 它不会阻止线程在通道上执行
read(...)
呼叫。您可以使用Future.isDone()
以避免以后阻止。
(当然,I/O使用Selector
可以是异步的太...取决于你如何使用API)。
相反,如果你读一个FileChannel
并没有当前可用的数据,线程块...(通常)直到数据可用。
简而言之,大多数操作系统不会将常规文件视为可以阻止的内容 - 因此它们不允许您明确地将它们设置为非阻止状态。
文件I/O只能被阻塞,因为它们被认为是非阻塞的?你是什么意思?在编程中,每个操作都被阻止。 – Val 2012-06-22 08:33:56
@Val我同意这里的措辞不是最好的。在编程中,并不是每个操作都被阻塞(从某种意义上讲,它会将进程或线程置于阻塞状态)。我的意思是,对于一个普通的文件,操作系统级别的API假定read()/ write()/ open()和其他对常规文件的调用是非阻塞的,但这是一个错误的假设。常规/标准操作系统级别的API无法将文件的句柄从阻塞更改为非阻塞。 (这是你可以用插座和管柄来做的事情)。 – nos 2012-06-22 09:28:45
@nos操作系统级别的API假设'read()/ write()/ open()'和其他调用是* blocking *。不清楚你在说什么。 – EJP 2017-05-23 11:17:17
+1。 asynchronousFileChannel支持异步I/O而非非阻塞。请检查。谢谢。 – Trying 2013-07-12 00:27:59
@Trying - 我已解决您的评论。 (我并不完全同意......) – 2013-07-12 05:20:46
我在['WindowsAsynchronousFileChannelImpl']中看不到任何内容(http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40 -b43/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java)“受益于Windows上的非阻塞API”。请澄清,或更正。异步I/O更像是阻塞在单独线程上执行的I/O,而非像非阻塞I/O那样。 – EJP 2017-05-23 11:16:13