`
zhouchaofei2010
  • 浏览: 1085051 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

java并发编程实战-第7章-取消与关闭

 
阅读更多

java并发编程实战-第7章-取消与关闭

  java中没有一种安全的抢占式方式的,只有协作式

  

  取消标志如果和阻塞方法一起使用,则会失效,如

   public void run() {

        try {

            BigInteger p = BigInteger.ONE;

            while (!cancelled)

                queue.put(p = p.nextProbablePrime());

        } catch (InterruptedException consumed) { }

    }

 

    public void cancel() { cancelled = true;  }

 

  如果任务代码可以响应中断,则可以使用中断作为取消机制

  

 7.1.2 中断策略

  形式 :线程级  服务级

  只有实现了线程中断策略的代码才可以屏蔽中断请求,在常规的任务和库代码中不应该屏蔽中断请求

 7.1.6 处理不可中断的取消

   public void  interrupt()  {

        try {

            socket.close();

        }

        catch (IOException ignored) { }

        finally {

            super.interrupt();

        }

    }

7.1.7     采用newTaskFor来封装非标准的取消

  这是java 6 在ThreadPoolExecutor中的新增功能,这是个工厂方法,创建Future来代表任务,返回

 

RunnableFutrure接口,改接口扩展了Future和Runnable(并由FutureTask实现)

   

  ThreadPoolExecutor中的cancel是调用newTaskFor返回的FunnableFutrure来取消操作的

  

   通过定制Future 改变Future.cancel的行为,通过改写newTaskFor方法

   

   

   ThreadPoolExecutor在哪里调用到了Future的cancel方法呢?

   

   父类:AbstractExecutorService 在invokeAll 等invokeXXX方法中的最后finally

   ...

   finally {

            if (!done)

                for (Future<T> f : futures)

                    f.cancel(true);

        }

   

7.2 停止基于线程的服务

应用程序拥有服务,服务拥有线程,应用程序没有直接拥有线程,所以不能通过应用程序关闭线程,相反,

 

服务应该提供生命周期的方法。

比如,ExcutorService提供shutdown 和shiutdownNow方法

 

 

7.2.1 示例:日志服务

  生产者-消费者

  

  在关闭时候需要给一个isShutDown标志

  

  Loger在消费时判断isShutDown需要同步,生产者在loger的queue.put(msg)的时候也需要同步

  

  如果关闭后,队列中还有内容,则loger还得继续记录日志,用reservations 来计数

  

  

7.2.2 关闭ExecutorService

      所有权链  

       

     使用ExecutorService的日志服务,比7.2.1的示例方面简洁多了

     

 

7.2.3 ”毒丸“对象

 

    关闭生产者-消费者的一种方式

    

    毒丸功能和7.2.1 中reservations一样,提供是否还有任务的标志

    

    只有在生产者和消费者都已知的情况下才使用毒丸

    

7.2.4  示例:只执行一次的服务

    

7.2.5 shutdownNow的局限性 

    

     该方法能返回已提交但未开始的任务,但不会返回关闭时已经开始正在执行的任务

     

     可以用继承的方式扩展功能,添加getCancelledTasks()方法

     

  public class TrackingExecutor extends AbstractExecutorService {

   private final ExecutorService exec;

   private final Set<Runnable> tasksCancelledAtShutdown =

       Collections.synchronizedSet(new HashSet<Runnable>());

   ...

   public List<Runnable> getCancelledTasks() {

       if (!exec.isTerminated())

           throw new IllegalStateException(...);

       return new ArrayList<Runnable>(tasksCancelledAtShutdown);

   }

 

   public void execute(final Runnable runnable) {

       exec.execute(new Runnable() {

           public void run() {

               try {

                   runnable.run();

               } finally {

                   if (isShutdown()

                       && Thread.currentThread().isInterrupted())

                       tasksCancelledAtShutdown.add(runnable);

               }

           }

       });

   }

 

   // delegate other ExecutorService methods to exec

}

 

7.3 处理非正常的线程终止

 

    在GUI丢失事件分派线程的时候情况比较严重,应用程序停止处理事件,GUI停止响应

    

    

    典型的线程池工作者结构,

    

    

    public void run() {

    Throwable thrown = null;

    try {

        while (!isInterrupted())

            runTask(getTaskFromWorkQueue());

    } catch (Throwable e) {

        thrown = e;

    } finally {

        threadExited(this, thrown);

    }

    

  }

 

  工作原理:当捕捉到未检测异常时,会终止该线程,但在终止之前,会通知框架,然后由框架来决定是否

 

用新线程代替或者用线程池的其它线程代替,

            ThreadPoolExcutor和Swing都是通过该技术来确保糟糕的任务不会影响到后续任务的执行

            

 

7.3.1 未捕获异常的处理UncaughtExceptionHandler 

 

        该方法与如上的主动获取方法互补,UncaughtExceptionHandler如何处理异常取决于服务质量的需

 

求,最常见的是把错误信息以及相应的栈追踪信息写入到应用程序日志中

        

        

Listing 7.25. UncaughtExceptionHandler that Logs the Exception.

public class UEHLogger implements Thread.UncaughtExceptionHandler {

   public void uncaughtException(Thread t, Throwable e) {

       Logger logger = Logger.getAnonymousLogger();

       logger.log(Level.SEVERE,

             "Thread terminated with exception: " + t.getName(),

             e);

   }

}

 

 If you want to be notified when a task fails due to an exception so that you can take some 

 

task-specific recovery action, 

 either wrap the task with a Runnable or Callable that catches the exception or override the 

 

afterExecute hook in THReadPoolExecutor.

 

 

 

 令人困惑的:异常提交给UncaughtExceptionHandler ,只有对于execute有效,对submit无效,如果

 

submit提交的任务抛出了异常,那么这个异常将被Future.get封装在ExecutionException中重新抛出

 

 

 参考:zhouchaofei2010.iteye.com/blog/2128389  源代码分析为什么ThreadPoolExcutor的Submit方法不

 

会把运行时的异常交给UncaughtExceptionHandler处理

 

 

 

7.4 JVM 关闭

  

7.4.1 关闭钩子

   正常关闭:调用关闭钩子

   Listing 7.26. Registering a Shutdown Hook to Stop the Logging Service.

public void start() {

   Runtime.getRuntime().addShutdownHook(new Thread() {

       public void run() {

           try { LogService.this.stop(); }

           catch (InterruptedException ignored) {}

       }

   });

}

 

  非正常:

  

7.4.2 守护线程

 

在jvm启动过程中创建的线程。除了主线程,其他的都是守护线程

 

应少用守护线程,因为jvm 关闭时,守护线程会被抛弃,既不会执行finally代码块,也不会执行回卷栈

 

 

7.4.3  终结器

 

避免使用终结器,用finally代码块或显示close()代替

 

 

小结:

java中没有一种安全的抢占式方式的,只有协作式,要依赖于协议与是否遵守这些协议

 

Using FutureTask and the Executor framework simplifies building cancellable tasks 

 

 

FutureTask 既可以在ExcutorService中使用,也可以再Thread 中使用

 

 

分享到:
评论

相关推荐

    Java并发编程实战

    第7章 取消与关闭 第8章 线程池的使用 第9章 图形用户界面应用程序 第三部分 活跃性、性能与测试 第10章 避免活跃性危险 第11章 性能与可伸缩性 第12章 并发程序的测试 第四部分 高级主题 第13章 显式锁 第...

    Java并发编程实战2019.zip

    Java并发编程实战,第1章 简介,第2章 线程安全性 第3章 对象的共享 第4章 对象的组合 第5章 基础构建模块 第6章 任务执行 第7章 取消与关闭 第8章 线程池的使用 第9章 图形用户界面应用程序 第10章 避免...

    Java 并发编程实战

    第7章 取消与关闭 第8章 线程池的使用 第9章 图形用户界面应用程序 第三部分 活跃性、性能与测试 第10章 避免活跃性危险 第11章 性能与可伸缩性 第12章 并发程序的测试 第四部分 高级主题 第13章 显式锁 第...

    Java 9并发编程实战手册

    Java 7并发编程实战手册的英文第二版(2017.5)

    Java 7并发编程实战手册

    《Java 7并发编程实战手册》是Java 7并发编程的实战指南,介绍了Java 7并发API中大部分重要而有用的机制。全书分为9章,涵盖了线程管理、线程同步、线程执行器、Fork/Join框架、并发集合、定制并发类、测试并发应用...

    Java并发编程实践 PDF 高清版

    第7章 取消和关闭 7.1 任务取消 7.2 停止基于线程的服务 7.3 处理反常的线程终止 7.4 JVM关闭 第8章 应用线程池 8.1 任务与执行策略问的隐性耦合 8.2 定制线程池的大小 8.3 配置ThreadPoolExecutor 8.4 扩展...

    龙果 java并发编程原理实战

    龙果 java并发编程原理实战 第2节理解多线程与并发的之间的联系与区别 [免费观看] 00:11:59分钟 | 第3节解析多线程与多进程的联系以及上下文切换所导致资源浪费问题 [免费观看] 00:13:03分钟 | 第4节学习并发的四...

    《Java并发编程的艺术》源代码

    第1章介绍Java并发编程的挑战,向读者说明进入并发编程的世界可能会遇到哪些问题,以及如何解决。 第2章介绍Java并发编程的底层实现原理,介绍在CPU和JVM这个层面是如何帮助Java实现并发编程的。 第3章介绍深入介绍...

    Java并发编程的艺术.md

    《Java并发编程的艺术》笔记 第一章 并发编程的挑战 第二章 Java并发机制的底层实现原理 volatile的两条实现原则: 1. Lock前缀指令会引起处理器缓存回写到内存 2. 一个处理器的缓存回写到内存会导致其他...

    汪文君高并发编程实战视频资源下载.txt

    │ Java并发编程.png │ ppt+源码.rar │ 高并发编程第二阶段01讲、课程大纲及主要内容介绍.wmv │ 高并发编程第二阶段02讲、介绍四种Singleton方式的优缺点在多线程情况下.wmv │ 高并发编程第二阶段03讲、...

    Java 并发编程原理与实战视频

    java并发编程原理实战 第2节理解多线程与并发的之间的联系与区别 [免费观看] 00:11:59分钟 | 第3节解析多线程与多进程的联系以及上下文切换所导致资源浪费问题 [免费观看] 00:13:03分钟 | 第4节学习并发的四个...

    Java并发编程的艺术

    第1章介绍Java并发编程的挑战,会向读者说明可能会遇到哪些问题,以及如何解决。第2章Java并发编程的底层实现原理,从CPU和JVM2个层面剖析。第3章详细深入介绍了Java的内存模型。第4章从介绍多线程技术带来的好处...

    Java并发编程的艺术_非扫描

    Java并发编程的艺术_非扫描本书特色本书结合JDK的源码介绍了Java并发框架、线程池的实现原理,帮助读者做到知其所以然。本书对原理的剖析不仅仅局限于Java层面,而是深入到JVM,甚至CPU层面来进行讲解,帮助读者从更...

    汪文君高并发编程实战视频资源全集

    │ Java并发编程.png │ ppt+源码.rar │ 高并发编程第二阶段01讲、课程大纲及主要内容介绍.wmv │ 高并发编程第二阶段02讲、介绍四种Singleton方式的优缺点在多线程情况下.wmv │ 高并发编程第二阶段03讲、...

    龙果java并发编程完整视频

    第7节多种创建线程的方式案例演示(一)带返回值的方式00:17:12分钟 | 第8节多种创建线程的方式案例演示(二)使用线程池00:15:40分钟 | 第9节Spring对并发的支持:Spring的异步任务00:11:10分钟 | 第10节使用jdk...

    java并发编程

    第7节多种创建线程的方式案例演示(一)带返回值的方式00:17:12分钟 | 第8节多种创建线程的方式案例演示(二)使用线程池00:15:40分钟 | 第9节Spring对并发的支持:Spring的异步任务00:11:10分钟 | 第10节使用jdk...

    实战Java高并发程序设计(第2版)PPT模板.pptx

    3jdk并发包 03 实战Java高并发程序设计(第2版)PPT模板全文共25页,当前为第7页。 3jdk并发包 3.1多线程的团队协作:同步控制 3.2线程复用:线程池 3.3不要重复发明轮子:jdk的并发容器 3.4使用jmh进行性能测试 ...

    scala编程中文pdf

    scala编程 33章 中文pdf Scala编程实战 目录 第1章字符串. 11 第2章数值39 第3章控制结构.60 第4章类和属性.103 第5章方法147 第6章对象170 第7章包和导入.190 第8章特质200 第9章函数式编程214 第10 章集合242 第...

Global site tag (gtag.js) - Google Analytics