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而已,不影响.
     
  • 相关阅读:
    PAT (Basic Level) Practise 1013 数素数
    PAT (Basic Level) Practise 1014 福尔摩斯的约会
    codeforces 814B.An express train to reveries 解题报告
    KMP算法
    rsync工具
    codeforces 777C.Alyona and Spreadsheet 解题报告
    codeforces 798C.Mike and gcd problem 解题报告
    nginx + tomcat多实例
    MongoDB副本集
    指针的艺术(转载)
  • 原文地址:https://www.cnblogs.com/youxin/p/3587311.html
Copyright © 2011-2022 走看看