Java多线程实践之—终结

来源:互联网 发布:dnf修改时装软件 编辑:程序博客网 时间:2024/05/16 19:41

这一节学习线程的终结

1. 终结

(1)线程终结的情况:线程死亡的一正常方式是从run()方法返回,但是线程还可以被中断!

(2)阻塞的情况

先了解下什么情况下一个线程将会进入阻塞状态:
1)通过调用sleep()方法,进入休眠状态;
2)通过调用wait()方法,直到notify()或notifyAll()消息【java.util.concurrent类库中的signal()和signalAll()】;
3)等待某个输入/ 输出完成;
4)在同步对象上调用其同步控制方法,但是对象锁不可用,因为另一个线程已经获得锁。

(3)中断

在run()方法中间打断(设置中断标志)线程运行,会抛出异常(异常抛出后,中断标志位复位)。Thread.interrupted()提供了离开run()循环而不抛出异常的第二种方法。为了调用interrupted(),必须先持有Thread对象,但是在concurrent类库中,似乎在避免对Thread的直接操作,转而使用Executors来执行所有操作。在Executors上调用shutdownNow(),那么它将发送一个interrupt()调用给它启动的所有线程。但是当你想要中断某一任务时,只能通过submit()而不是execute()来启动任务,submit将返回一个泛型Future<?>(与Callable接口不同,这里不需要调用get()方法),然后可以再Future上调用cancel()方法,将true传递给cancel,那么它将会调用interrupt()来停止这个线程。贴上代码,在分析!
package zy.thread.demo;import java.io.IOException;import java.io.InputStream;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;import java.util.concurrent.TimeUnit;public class Interrupting {private static ExecutorService exec = Executors.newCachedThreadPool();static void test(Runnable r) throws InterruptedException {Future<?> future = exec.submit(r);TimeUnit.MILLISECONDS.sleep(100);System.out.println("Interrupting " + r.getClass().getName());future.cancel(true);System.out.println("Interrup sent to " + r.getClass().getName());}public static void main(String[] args) throws InterruptedException {test(new SleepBlocked());test(new IOBlocked(System.in));test(new SynchronizedBlocked());TimeUnit.SECONDS.sleep(3);System.out.println("Aborting with System.exit(0)");System.exit(0);}}class SleepBlocked implements Runnable {@Overridepublic void run() {try {TimeUnit.SECONDS.sleep(100);} catch (InterruptedException e) {System.out.println("InterruptedException");}System.out.println("Exiting SleepBlocked.run()");}}class IOBlocked implements Runnable {private InputStream in;public IOBlocked(InputStream in) {this.in = in;}@Overridepublic void run() {try {System.out.println("Waiting for read():");in.read();} catch (IOException e) {if (Thread.currentThread().isInterrupted())System.out.println("Interrupted from blocked I/O");elsethrow new RuntimeException(e);}System.out.println("Exiting IOBlocked.run()");}}class SynchronizedBlocked implements Runnable {public synchronized void f() {while (true)Thread.yield();}public SynchronizedBlocked() {new Thread() {public void run() {f();}}.start();}@Overridepublic void run() {System.out.println("Trying to call f()");f();System.out.println("Exiting SynchronizedBlocked.run()");}}
Output : 95%匹配(5%是因为,SleepBlocked执行结果顺序无法预测)
分析:I/O和synchronized块上的等待不能被中断,那怎么办呢?在I/O上的阻塞,可以关闭任务在其上发生阻塞的底层资源:
package zy.thread.demo;import java.io.InputStream;import java.net.ServerSocket;import java.net.Socket;import java.util.concurrent.*;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);    System.out.println("Shutting down all threads");    exec.shutdownNow();        TimeUnit.SECONDS.sleep(1);    System.out.println("Closing " + socketInput.getClass().getName());    socketInput.close();         TimeUnit.SECONDS.sleep(1);    System.out.println("Closing " + System.in.getClass().getName());    System.in.close();}}
synchronized方法或临界区上的阻塞不可中断,但是ReentranLock上的阻塞则可以:
package zy.thread.demo;import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class Interrupting2 {public static void main(String[] args) throws InterruptedException {Thread t = new Thread(new Blocked2());    t.start();    TimeUnit.SECONDS.sleep(1);    System.out.println("Issuing t.interrupt()");    t.interrupt();}}class BlockedMutex {  private Lock lock = new ReentrantLock();  public BlockedMutex() {    lock.lock();  }  public void f() {    try {    // This will never be available to a second task    lock.lockInterruptibly(); // Special call    System.out.println("lock acquired in f()");    } catch(InterruptedException e) {    System.out.println("Interrupted from lock acquisition in f()");    }  }}class Blocked2 implements Runnable {  BlockedMutex blocked = new BlockedMutex();  public void run() {  System.out.println("Waiting for f() in BlockedMutex");  blocked.f();  System.out.println("Broken out of blocked call");  }}

下一篇:线程的协作!

0 0