zoukankan      html  css  js  c++  java
  • 多线程Two-Phase Termination Pattern两阶段终止模式

    一 Two-Phase Termination Pattern

      Two-Phase Termination Pattern,指的就是当希望结束一个线程的时候,送出一个终止请求,但是不会马上停止,做一些刷新工作。进入“终止处理中”,在该状态下,不会进行该线程日常工作任务的操作,而是进行一些终止操作。

       这个方式所考虑的因素如下

      1,必须要考虑到使得该线程能够安全的结束,Thread中的stop会有问题的,因为它会不管线程执行到哪里,都会马上停止,不能保证安全的结束。

      2,一定能够进行正常的终止处理,在java中,这点可以使用finally来实现

      3,能够高响应的终止,收到终止后,当线程在wait或者sleep或者join的时候,不用等到时间到才终止,而是马上中断线程的这些状态,进而进行终止操作。

       当一个线程正在执行周期性的工作时候,在“作业中”发了停止执行绪的请求,此时该线程不能马上离开停止,而应该先做完本次周期内部的工作,然后进入“善后阶段”完成一些善后的工作,所谓的两阶段终止,即中止“运作阶段”,并完成“善后阶段”,完整的完成执行绪的工作。

    两阶段终止线程的架构模式如下:

    public class WorkerTerminalThread extends Thread {
           // 已经送出终止请求为true,初始化的时候为false
           //由于该字段可能会被多个线程访问修改,为了保护就使用这个
        private volatile boolean shutdownRequested = false;
        // 终止请求
        public void shutdownRequest() {
            shutdownRequested = true;
            interrupt();
        }
        public boolean isShutdownRequest() {
            return shutdownRequested;
        }
        // 具体动作
        public final void run() {
            try {
                while (!shutdownRequested)
                    doWork();
            } catch (InterruptedException e) {
            }
            // 终止处理中的工作,不会进行平常操作,但是会进行终止处理
            finally {
                doShutdown();
            }
        }
        // 具体工作操作
        private void doWork() throws InterruptedException {
        }
        // 终止后进行善后处理
        private void doShutdown()
        {
        }
    }

    解释:

      1,利用Volatile的原因是,这个字段可能会被多个线程所使用,进行修改,为了保护该字段,则可以利用同步方法或者同步代码块来保护,或者利用Volatile。用Volatile修饰的字段,强制了该成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。

      2,这里运用了标识和中断状态来终止线程,之所以不单独用一个。原因是如果仅仅利用标识,无法是的那些处于wait、sleep或者join中的线程马上停止,响应性就会很差。加入了interrupt后,就可以立刻使得这些状态下的线程中断。如果仅仅利用interrupt,由于interrupt仅仅对于wait,sleep或join处进行抛出异常,如果工作代码执行在catch里,捕获了InterruptedException后,则此时interrupt就不起作用了。

    转自:http://computerdragon.blog.51cto.com/6235984/1206548

    例子:

    为上面的2个方法添加如下:

     private long counter = 0;  

       //  作业  
        private void doWork() throws InterruptedException {  
            counter++;  
            System.out.println("doWork: counter = " + counter);  
            Thread.sleep(500);  
        }  
      
        // 终止处理  
        private void doShutdown() {  
            System.out.println("doShutdown: counter = " + counter);  
        }  
     
    public class Test {  
        public static void main(String[] args) {  
            System.out.println("main: BEGIN");  
            try {  
                 
                TwoPhaseThread t = new  TwoPhaseThread();  
                t.start();  
      
                Thread.sleep(10000);  
      
                System.out.println("main: shutdownRequest");  
                t.shutdownRequest();  
      
                System.out.println("main: join");  
      
      
                t.join();  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
            System.out.println("main: END");  
        }  
    }  

    输出:

    main: BEGIN
    doWork: counter = 1
    doWork: counter = 2
    doWork: counter = 3
    doWork: counter = 4
    doWork: counter = 5
    doWork: counter = 6
    doWork: counter = 7
    doWork: counter = 8
    doWork: counter = 9
    doWork: counter = 10
    doWork: counter = 11
    doWork: counter = 12
    doWork: counter = 13
    doWork: counter = 14
    doWork: counter = 15
    doWork: counter = 16
    doWork: counter = 17
    doWork: counter = 18
    doWork: counter = 19
    doWork: counter = 20
    main: shutdownRequest
    main: join
    doShutdown: counter = 20
    main: END

    评论:

    Volatile这个修饰符在该例子中不可能被多个线程共享吧? 是不是需要在volatile前加static参数, 才可以算作是共享该变量呢? 谢谢~


    2013-05-23 18:17:23
    回复 liuyuanhui0301:[1楼]

    线程是共享实例的所有的字段,不管是用什么修饰符的。这里加上这个关键之处就是,有可能会有多个线程对于该变量进行修改,当然这里也可以不加,因为修改这个变量的值只会是true而已,不影响.
     
  • 相关阅读:
    Android开发新手学习总结(六)——android开发目录结构【图文版】
    Android开发新手学习总结(一)——使用Android Studio搭建Android集成开发环境
    62个Android Studio小技巧合集
    Android Studio 入门指南
    Unity操作
    Unity的安装和破解
    pb数据窗口设置操作
    Roll A Ball
    c实现旋转数列
    用循环添加多行、多列视图
  • 原文地址:https://www.cnblogs.com/youxin/p/3587311.html
Copyright © 2011-2022 走看看