多线程程序设计学习(11)Two-phapse-Termination pattern
Two-phapse-Termination[A终止B线程]
一:Two-phapse-Termination的参与者
--->A线程
--->B线程
二:Two-phapse-Termination模式什么时候使用
--->当A线程需要B线程终止时
三:Two-phapse-Termination思考
---> 优雅的终止线程
(1)安全地终止(安全性)==>即使收到终止请求,也不会马上结束线程,而是表示收到终止请求的标识。以对象不被损坏为前提,安全终止
(2)一定会进行终止处理(生命性)==>当收到终止请求,会中断掉可以中断的wait,前往终止处理。异常处理要非常小心,防止抛出异常,破坏对象。
(3)送出终止请求后,要尽快进入终止处理(响应性)==>当收到终止请求,可以中断掉Sleep,尽快终止处理
四进阶说明
--->首先来说说java中的中断机制,Java 中断机制是一种协作机制,也就是说通过中断并不能直接终止另一个线程,而需要被中断的线程自己处理中断。当调用interrupt()方法的时候,只是设 置了要中断线程的中断状态,而此时被中断的线程的可以通过isInterrupted()或者是interrupted()方法判断当前线程的中断状态是
--->interrupte()和interrupted()和isInterrputed()方法的区别
(1)线程对象.interrupte()是将调用该方法的对象所指的线程的中断状态修改为:【中断状态】
(2)Thead.interrputed()是检查当前线程的中断状态,如果为中断状态,则返回true,并将中断状态清除掉。如果为非中断状态,返回false
(3)线程对象.isInterrputed()是返回当前线程是否为中断状态,并不会修改线程的中断状态
---->wait方法被中断后,不会立马跑出InterrptedException,而是要重新获取锁定,才可抛出该异常。
--->书上一种解释:
A线程中b.interrput()执行,B线程正处于sleep或wait状态,则会立马提前放弃休眠或等待,抛出interrputedException异常。线程的【中断状态】会立马被清除掉。
【测试未得到印证】
-->书上另一种解释
A线程中b.interrpt()执行,B线程刚开始准备执行sleep或wait,执行时会检查线程的状态,如果为中断状态,则跑出InterrptedException异常。线程的【中断状态】会立马被清除掉。
Two-phapse-Termination 例子
主线程A(要停掉B线程)
1 package com.yeepay.sxf.thread10; 2 /** 3 * 测试主线程A线程 4 * @author sxf 5 * 6 */ 7 public class Test { 8 public static void main(String[] args) { 9 //开启收拾玩具的线程 10 CountAddThread addThread=new CountAddThread(); 11 //开启线程 12 new Thread(addThread).start(); 13 //让主线程休息5秒 14 try { 15 Thread.sleep(5000); 16 } catch (InterruptedException e) { 17 // TODO Auto-generated catch block 18 e.printStackTrace(); 19 } 20 //关闭收拾玩具线程 21 addThread.shutDownRequest(); 22 23 } 24 }
线程B(要被A线程停掉)
1 package com.yeepay.sxf.thread10; 2 3 public class CountAddThread extends Thread{ 4 //计数器 5 private Integer counter=0; 6 7 //当发送出停止线程的请求,该值设置为true 8 private volatile boolean flag=false; 9 10 @Override 11 public void run() { 12 try { 13 while (!flag) { 14 doWork(); 15 if(this.interrupted()){ 16 System.out.println("CountAddThread.run(中断)"); 17 }else{ 18 System.out.println("CountAddThread.run(非中断)"); 19 } 20 System.out.println("CountAddThread.run(sleep after收拾玩具个数:)"+counter); 21 } 22 } catch (Exception e) { 23 System.out.println("CountAddThread.run(取消sleep后,抛出异常抓住,收拾玩具个数:)"+counter); 24 e.printStackTrace(); 25 }finally{ 26 shutDownDoWork(); 27 } 28 29 30 } 31 32 //具体工作内容 33 public void doWork() throws InterruptedException { 34 counter++; 35 System.out.println("CountAddThread.doWork(收拾玩具第)"+counter+"次数"); 36 // Thread.sleep(10); 37 } 38 39 //发送终止请求 40 public void shutDownRequest(){ 41 System.out.println("CountAddThread.shutDownRequest(终止线程方法的请求启动)"); 42 flag=true; 43 //将线程设置为中断状态 44 interrupt(); 45 //判断this线程是否为中断状态 46 if(this.isInterrupted()){ 47 System.out.println("CountAddThread.shutDownRequest(线程是中断)"); 48 }else{ 49 System.out.println("CountAddThread.shutDownRequest(线程为非中断状态)"); 50 } 51 52 } 53 54 //判断终止请求是否已经发出 55 public boolean isShutDown(){ 56 return flag; 57 } 58 59 public void shutDownDoWork(){ 60 System.out.println("CountAddThread.shutDownDoWork(结束请求后counter=>"+counter+")"); 61 } 62 63 64 }
一种异常抛出的实现
1 package com.yeepay.sxf.thread10; 2 /** 3 * 抛异常一种实现 4 * @author sxf 5 * 6 */ 7 public class TestException { 8 9 private Exception exception=null; 10 11 public static void main(String[] args) { 12 TestException ex=new TestException(); 13 try { 14 ex.addtest(); 15 } catch (Exception e) { 16 // TODO Auto-generated catch block 17 System.out.println("TestException.main()"+e); 18 } 19 } 20 21 public void addtest() throws Exception{ 22 try { 23 int a=1/1; 24 } catch (Exception e) { 25 exception=e; 26 } 27 System.out.println("异常被抓住,但没抛,也没打印,而是赋值给别的对象,后边再抛"); 28 if(exception!=null){ 29 throw exception; 30 } 31 System.out.println("抛异常后边不可以写代码,也不会执行"); 32 } 33 34 }