Java多线程实践之—终结
2015-08-18 12:48
519 查看
这一节学习线程的终结
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 { @Override public 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; } @Override public 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"); else throw 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(); } @Override public 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"); } }
下一篇:线程的协作!
相关文章推荐
- 《精通hibernate:java持久化...》---持久化类
- 基于Java的拼图游戏
- springMvc里的mvc:resources与静态资源的访问
- Java的垃圾回收机制GC
- spring MVC项目中,欢迎页首页根路径到底是怎么设置的
- JAVA之Timer定时器
- Java总的Static关键字
- Java中创建对象的四种方法
- JAVA 用递归实现求五的阶乘
- JAVA创建对象的4种方式
- HBase的JAVA API操作详解
- java 之 面向对象
- java.lang.IllegalAccessError: class com.google.protobuf.HBaseZeroCopyByteString
- java.lang.IllegalAccessError: class com.google.protobuf.HBaseZeroCopyByteString
- 将activiti整合到spring里
- Java并发编程:Callable、Future和FutureTask
- 在Eclipse中导入android studio项目
- eclipse常用快捷键
- 【Java并发编程实战】-----synchronized
- Java --- 商品分页