首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Thread的中断机制(3)

Thread的中断机制(3)

一旦Example3中的Thread.interrupt()被调用,线程便收到一个异常,于是逃离了阻塞状态并确定应该停止。上面我们还可以使用共享信号量来替换!Thread.currentThread().isInterrupted()条件,但不如它简洁。
死锁状态线程无法被中断Example4试着去中断处于死锁状态的两个线程,但这两个线都没有收到任何中断信号(抛出异常),所以interrupt()方法是不能中断死锁线程的,因为锁定的位置根本无法抛出异常:
[url=][/url]
class Example4 extends Thread {    public static void main(String args[]) throws Exception {        final Object lock1 = new Object();        final Object lock2 = new Object();        Thread thread1 = new Thread() {            public void run() {                deathLock(lock1, lock2);            }        };        Thread thread2 = new Thread() {            public void run() {                // 注意,这里在交换了一下位置                deathLock(lock2, lock1);            }        };        System.out.println("Starting thread...");        thread1.start();        thread2.start();        Thread.sleep(3000);        System.out.println("Interrupting thread...");        thread1.interrupt();        thread2.interrupt();        Thread.sleep(3000);        System.out.println("Stopping application...");    }    static void deathLock(Object lock1, Object lock2) {        try {            synchronized (lock1) {                Thread.sleep(10);// 不会在这里死掉                synchronized (lock2) {// 会锁在这里,虽然阻塞了,但不会抛异常                    System.out.println(Thread.currentThread());                }            }        } catch (InterruptedException e) {            e.printStackTrace();            System.exit(1);        }    }}[url=][/url]

中断I/O操作然而,如果线程在I/O操作进行时被阻塞,又会如何?I/O操作可以阻塞线程一段相当长的时间,特别是牵扯到网络应用时。例如,服务器可能需要等待一个请求(request),又或者,一个网络应用程序可能要等待远端主机的响应。


实现此InterruptibleChannel接口的通道是可中断的:如果某个线程在可中断通道上因调用某个阻塞的 I/O 操作(常见的操作一般有这些:serverSocketChannel. accept()、socketChannel.connect、socketChannel.open、socketChannel.read、socketChannel.write、fileChannel.read、fileChannel.write)而进入阻塞状态,而另一个线程又调用了该阻塞线程的 interrupt 方法,这将导致该通道被关闭,并且已阻塞线程接将会收到ClosedByInterruptException,并且设置已阻塞线程的中断状态。另外,如果已设置某个线程的中断状态并且它在通道上调用某个阻塞的 I/O 操作,则该通道将关闭并且该线程立即接收到 ClosedByInterruptException;并仍然设置其中断状态。如果情况是这样,其代码的逻辑和第三个例子中的是一样的,只是异常不同而已。


如果你正使用通道(channels)(这是在Java 1.4中引入的新的I/O API),那么被阻塞的线程将收到一个ClosedByInterruptException异常。但是,你可能正使用Java1.0之前就存在的传统的I/O,而且要求更多的工作。既然这样,Thread.interrupt()将不起作用,因为线程将不会退出被阻塞状态。Example5描述了这一行为。尽管interrupt()被调用,线程也不会退出被阻塞状态,比如ServerSocket的accept方法根本不抛出异常。


很幸运,Java平台为这种情形提供了一项解决方案,即调用阻塞该线程的套接字的close()方法。在这种情形下,如果线程被I/O操作阻塞,当调用该套接字的close方法时,该线程在调用accept地方法将接收到一个SocketException(SocketException为IOException的子异常)异常,这与使用interrupt()方法引起一个InterruptedException异常被抛出非常相似,(注,如果是流因读写阻塞后,调用流的close方法也会被阻塞,根本不能调用,更不会抛IOExcepiton,此种情况下怎样中断?我想可以转换为通道来操作流可以解决,比如文件通道)。下面是具体实现:
[url=][/url]
class Example6 extends Thread {    volatile ServerSocket socket;    public static void main(String args[]) throws Exception {        Example6 thread = new Example6();        System.out.println("Starting thread...");        thread.start();        Thread.sleep(3000);        System.out.println("Asking thread to stop...");        Thread.currentThread().interrupt();// 再调用interrupt方法        thread.socket.close();// 再调用close方法        try {            Thread.sleep(3000);        } catch (InterruptedException e) {        }        System.out.println("Stopping application...");    }    public void run() {        try {            socket = new ServerSocket(8888);        } catch (IOException e) {            System.out.println("Could not create the socket...");            return;        }        while (!Thread.currentThread().isInterrupted()) {            System.out.println("Waiting for connection...");            try {                socket.accept();            } catch (IOException e) {                System.out.println("accept() failed or interrupted...");                Thread.currentThread().interrupt();//重新设置中断标示位            }        }        System.out.println("Thread exiting under request...");    }}
继承事业,薪火相传
返回列表