问题描述

我正在Java 1.6中使用一个ExecutoreService,简单地开始

ExecutorService pool = Executors.newFixedThreadPool(THREADS).

当我的主线程完成(以及由线程池处理的所有任务)时,此池将阻止我的程序关闭,直到我明确地调用

pool.shutdown();

我可以避免通过某种方式将这个池使用的内部线程管理转换成deamon线程来调用吗?或者我在这里遗漏了一些东西。

最佳解决方案

大概最简单和最优的解决方案是在Marco13’s answer中,所以不要被投票差异(我的回答是几年前)或接受标记(这意味着我的解决方案适合于OP情况不是最好的)。


您可以使用ThreadFactory将Executor中的线程设置为守护程序。这将影响执行器服务,它也将成为守护进程线程,因此如果没有其他non-daemon线程,它(以及由其处理的线程)将停止。这是一个简单的例子:

  1.  
    ExecutorService exec = Executors.newFixedThreadPool(4,
  2.  
    new ThreadFactory() {
  3.  
    public Thread newThread(Runnable r) {
  4.  
    Thread t = Executors.defaultThreadFactory().newThread(r);
  5.  
    t.setDaemon(true);
  6.  
    return t;
  7.  
    }
  8.  
    });
  9.  
     
  10.  
    exec.execute(YourTaskNowWillBeDaemon);

但是如果你想获得执行器,让它的任务完成,同时在应用程序完成后会自动调用它的shutdown()方法,你可能希望用Guava’s MoreExecutors.getExitingExecutorService来包装你的执行器。

  1.  
    ExecutorService exec = MoreExecutors.getExitingExecutorService(
  2.  
    (ThreadPoolExecutor) Executors.newFixedThreadPool(4),
  3.  
    100_000, TimeUnit.DAYS//period after which executor will be automatically closed
  4.  
    //I assume that 100_000 days is enough to simulate infinity
  5.  
    );
  6.  
    //exec.execute(YourTask);
  7.  
    exec.execute(() -> {
  8.  
    for (int i = 0; i < 3; i++) {
  9.  
    System.out.println("daemon");
  10.  
    try {
  11.  
    TimeUnit.SECONDS.sleep(1);
  12.  
    } catch (Exception e) {
  13.  
    e.printStackTrace();
  14.  
    }
  15.  
    }
  16.  
    });

次佳解决方案

已经有一个内置功能用于创建一个ExecutorService,在一段时间不活动后终止所有线程:您可以创建一个ThreadPoolExecutor,传递所需的时序信息,然后在此执行器服务上调用allowCoreThreadTimeout(true)

  1.  
    /**
  2.  
    * Creates an executor service with a fixed pool size, that will time
  3.  
    * out after a certain period of inactivity.
  4.  
    *
  5.  
    * @param poolSize The core- and maximum pool size
  6.  
    * @param keepAliveTime The keep alive time
  7.  
    * @param timeUnit The time unit
  8.  
    * @return The executor service
  9.  
    */
  10.  
    public static ExecutorService createFixedTimeoutExecutorService(
  11.  
    int poolSize, long keepAliveTime, TimeUnit timeUnit)
  12.  
    {
  13.  
    ThreadPoolExecutor e =
  14.  
    new ThreadPoolExecutor(poolSize, poolSize,
  15.  
    keepAliveTime, timeUnit, new LinkedBlockingQueue<Runnable>());
  16.  
    e.allowCoreThreadTimeOut(true);
  17.  
    return e;
  18.  
    }

EDIT Referring to the remarks in the comments: Note that this thread pool executor will not automatically shut down when the application exits. The executor will continue to run after the application exits, but no longer than the keepAliveTime. If, depending on the precise application requirements, the keepAliveTime has to be longer than a few seconds, the solution in the answer by Pshemo may be more appropriate: When the threads are set to be daemon threads, then they will end immediately when the application exits.

第三种解决方案

我会使用Guava的ThreadFactoryBuilder类。

ExecutorService threadPool = Executors.newFixedThreadPool(THREADS, new ThreadFactoryBuilder().setDaemon(true).build());

如果你还没有使用Guava,我会去一个ThreadFactory子类,如Pshemo’s answer顶部所述

第四种方案

是。

您只需创建自己的ThreadFactory类,即创建守护进程线程而不是常规线程。

参考文献

在Java中,将ExecutorService转为守护程序的更多相关文章

  1. 将java中Map对象转为有相同属性的类对象(json作为中间转换)

    java中Map对象转为有相同属性的类对象(json作为中间转换) 准备好json转换工具类 public class JsonUtil { private static ObjectMapper o ...

  2. Java 中的字符串转为二进制

    /** * 将字符串转为二进制 */ public class StrConversion { public static void main(String args[]) { String str ...

  3. java中list强转为map类型

    起因:读取数据库文件的测试用例,测试用例需要存放到一个map中,方便下次调用, 读取的内容返回的内容存放在一个list中,并且数据内容是key=value的形式,最开始使用切片方式,做了很多无用功,后 ...

  4. Java中ExecutorService和CompletionService区别

    我们现在在Java中使用多线程通常不会直接用Thread对象了,而是会用到java.util.concurrent包下的ExecutorService类来初始化一个线程池供我们使用. 之前我一直习惯自 ...

  5. java中ExecutorService接口

    一.声明 public interface ExecutorService extends Executor 位于java.util.concurrent包下 所有超级接口:Executor 所有已知 ...

  6. java中Executor、ExecutorService、ThreadPoolExecutor介绍(转)

    1.Excutor 源码非常简单,只有一个execute(Runnable command)回调接口 public interface Executor { /**     * Executes th ...

  7. java中把list列表转为arrayList以及arraylist数组截取的简单方法

    java中把list列表转为arrayList以及arraylist数组截取的简单方法 package xiaobai; import java.util.ArrayList; import java ...

  8. Java中数组转为List三种情况的优劣对比,常犯的类型转换错误原因解析

    一.最常见方式(未必最佳)通过 Arrays.asList(strArray) 方式,将数组转换List后,不能对List增删,只能查改,否则抛异常. 关键代码:List list = Arrays. ...

  9. java中Executor、ExecutorService、ThreadPoolExecutor介绍

    源码非常简单,只有一个execute(Runnable command)回调接口 public interface Executor { /**      * Executes the given c ...

随机推荐

  1. vue从入门到进阶:组件Component详解(六)

    一.什么是组件? 组件 (Component) 是 Vue.js 最强大的功能之一.组件可以扩展 HTML 元素,封装可重用的代码.在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功 ...

  2. 移动前端—H5实现图片先压缩再上传

    在做移动端图片上传的时候,用户传的都是手机本地图片,而本地图片一般都相对比较大,拿iphone6来说,平时拍很多图片都是一两M的,如果直接这样上传,那图片就太大了,如果用户用的是移动流量,完全把图片上 ...

  3. SAP MM 物料主数据采购视图中的字段'Var. OUn'的作用?

    SAP MM 物料主数据采购视图中的字段'Var. OUn'的作用? 物料主数据采购视图里有一个字段,叫做'Var. OUn'的, 如下图: 这个字段,笔者之前所参与的项目里,从来没有用过.所以,笔者 ...

  4. 浅析C/C++中的switch/case陷阱

    浅析C/C++中的switch/case陷阱 先看下面一段代码: 文件main.cpp #include<iostream> using namespace std; int main(i ...

  5. SparkSQL【1.x版本】字段敏感不敏感问题

    一.特征 1.SqlContext默认大小写不敏感,如果DataFrame中有字段相同,大小写不同,在使用字段的时候不会引起歧义. 2.HiveContext提供更多的Hive预置函数,可以更高效的进 ...

  6. HTMLTestRunner修改成Python3版本

    修改前:HTMLTestRunner下载地址:http://tungwaiyip.info/software/HTMLTestRunner.html BSTestRunner     下载地址:htt ...

  7. C#面向对象 1

    using System; using System.Collections.Generic; using System.Collections; using System.Linq; using S ...

  8. mssql 系统函数-字符串函数专题--字符串函数大全

    mssql 系统函数 字符串函数 substring 功能简介 mssql 系统函数 字符串函数 stuff 功能简介 mssql 系统函数 字符串函数 str 功能简介 mssql 系统函数 字符串 ...

  9. ArcGIS Server10.2 集群部署注意事项

    不接触Server很久了,最近一个省级项目需要提交一个部署方案,由于是省级系统,数据.服务数量都较大,需要考虑采用Server集群的方式来实现.在网上搜罗了以下Server集群的资料,按照步骤一步步来 ...

  10. git笔记(2)-常见命令的使用(详解待续)

    1. 常用命令 (1)git --help 帮助命令,其他的类似 (2)git branch 查看分支及其他(创建分支,查看远程分支名称等) (3)git checkout 切换分支以及其他 (3)g ...