这个程序想说明,因同步 IO 资源而阻塞的线程,可以通过关闭 IO 资源而停止阻塞。
//: concurrency/CloseResource.java
// Interrupting a blocked task by
// closing the underlying resource.
// {RunByHand}
import java.net.*;
import java.util.concurrent.*;
import java.io.*;
import static net.mindview.util.Print.*;
class IOBlocked implements Runnable {
private InputStream in;
public IOBlocked(InputStream is) { in = is; }
public void run() {
try {
print("Waiting for read():");
in.read();
} catch(Exception e) {
e.printStackTrace(); //这句是我加的
if(Thread.currentThread().isInterrupted()) {
print("Interrupted from blocked I/O");
} else {
throw new RuntimeException(e);
}
}
print("Exiting IOBlocked.run()");
}
}
public class CloseResource {
public static void main(String[] args) throws Exception {
ExecutorService exec = Executors.newCachedThreadPool();
ServerSocket server = new ServerSocket(8080);
InputStream socketInput =
new Socket("localhost", 8080).getInputStream();
exec.execute(new IOBlocked(socketInput));
exec.execute(new IOBlocked(System.in));
TimeUnit.MILLISECONDS.sleep(100);
print("Shutting down all threads");
exec.shutdownNow();
TimeUnit.SECONDS.sleep(1);
print("Closing " + socketInput.getClass().getName());
socketInput.close(); // Releases blocked thread
TimeUnit.SECONDS.sleep(1);
print("Closing " + System.in.getClass().getName());
System.in.close(); // Releases blocked thread
}
}/* Output: (85% match)
Waiting for read():
Waiting for read():
Shutting down all threads
Closing java.net.SocketInputStream
Interrupted from blocked I/O
Exiting IOBlocked.run()
Closing java.io.BufferedInputStream
Exiting IOBlocked.run() //书中的打印结果就有这句,而我的没有
*///:~
打印结果:
Waiting for read():
Waiting for read():
Shutting down all threads
Closing java.net.SocketInputStream
java.net.SocketException: Socket closed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:170)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at java.net.SocketInputStream.read(SocketInputStream.java:223)
at IOBlocked.run(Interrupting.java:24)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Interrupted from blocked I/O
Exiting IOBlocked.run()
Closing java.io.BufferedInputStream
执行后,程序无法结束,从打印结果也可以看出,第二个线程还是处于运行中。这个例子来自 java 编程思想,书中说到,两个线程都会因为资源的关闭而结束.
所以,为什么因为 System.in.read()而阻塞的线程,无法通过 System.in.close()唤醒(可能是以抛出异常的方式)?明明书中都说可以,难道是 java 版本问题
1
pursuer 2020-04-25 11:51:54 +08:00
应该和操作系统实现有关,我用 C 在 windows 下测试了下,stdin 在 read 堵塞的状态下,close 也会堵塞
|
2
sioncheng 2020-04-25 12:41:55 +08:00
看方法签名来解释?应该只是是 jvm 实现者的一些考虑和选择吧。毕竟操作系统层面的 socket api ( c/api ),也不是通过 exception 来表示 read 一个 closed 的 socket 。
/** * Reads the next byte of data from the input stream. The value byte is * returned as an <code>int</code> in the range <code>0</code> to * <code>255</code>. If no byte is available because the end of the stream * has been reached, the value <code>-1</code> is returned. This method * blocks until input data is available, the end of the stream is detected, * or an exception is thrown. * * <p> A subclass must provide an implementation of this method. * * @return the next byte of data, or <code>-1</code> if the end of the * stream is reached. * @exception IOException if an I/O error occurs. */ public abstract int read() throws IOException; |
3
amiwrong123 OP @pursuer
这么说,有可能是哈。我还忘说自己的环境了,win10,jdk8.也许作者跑程序不是在 Windows 上跑的。 |
4
amiwrong123 OP |
5
sioncheng 2020-04-25 15:20:46 +08:00
@amiwrong123,应该感知到了,你输出 System.in.read 返回到结果看看,应该是-1,它并不一定要通过异常告诉调用者吧。
|
6
johnj 2020-04-25 16:49:15 +08:00
别用 IDE 执行,再试试
|