【问题标题】:Understanding ThreadPoolExecutor with ThreadFactory in Java executors framework在 Java executors 框架中使用 ThreadFactory 理解 ThreadPoolExecutor
【发布时间】:2020-03-03 13:14:18
【问题描述】:

Official API docs 说:

使用ThreadFactory 创建新线程。如果没有另外指定,则使用Executors.defaultThreadFactory(),它创建的线程都处于相同的ThreadGroup 并具有相同的NORM_PRIORITY 优先级和非守护程序状态。通过提供不同的ThreadFactory,您可以更改线程的名称、线程组、优先级、守护进程状态等。

here 的一个例子有以下几行:

ThreadFactory threadFactory = Executors.defaultThreadFactory();
ThreadPoolExecutor executorPool = new ThreadPoolExecutor(2, 4, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(2), threadFactory, rejectionHandler);

我试图在上述代码的上下文中理解官方文档中引用文本的最后一句话。换句话说,我怎样才能通过不同的ThreadFactory 来改变线程的名称、线程组、优先级和守护进程状态?这应该如何实现?

【问题讨论】:

  • 您发布的代码使用了一个构造函数,该构造函数为执行程序指定了一个线程工厂。有什么问题?
  • ThreadFactory 是一个接口,你可以自己创建一个实现。
  • 所以我们自己实现ThreadFactory 是实现这一目标的唯一方法,而框架没有明确提供任何帮助器/实用程序类?不知何故,我觉得只提供接口并要求我们实现它以实现可能经常出现的用例场景有点不完整,并且提供这种实用程序工厂的预期框架。

标签: java multithreading


【解决方案1】:

ThreadFactory 是一个具有单一功能的接口,Thread newThread(Runnable r)。 ThreadFactory 的 Javadoc 中的示例实现:

 class SimpleThreadFactory implements ThreadFactory {
   public Thread newThread(Runnable r) {
     return new Thread(r);
   }
 }

Thread8 个不同的构造函数,允许您设置线程名称、堆栈大小和线程组。它还有几个可以调用的设置器,用于控制线程优先级、类加载器等。甚至可以返回 Thread 的某个子类,并带有您选择赋予它的任何行为。

因此,您可以创建自己的并将其实例传递给新的ThreadPoolExecutor,而不是传入Executors.defaultThreadFactory() 的返回值。

【讨论】:

    【解决方案2】:

    ThreadFactory 接口包含newThread(Runnable r) 方法。您可以实现它,以便创建的线程将具有更有意义的名称。

    例如:

      private final static String THREAD_NAME_TEMPLATE = "%s-pool-%d-thread-%d";
    
      @Override
      public Thread newThread(Runnable r) {
        Thread t = new Thread(group, r,
          String.format(THREAD_NAME_TEMPLATE, namePrefix, poolNumber, threadNumber.getAndIncrement()),
          0);
        t.setDaemon(false);
        t.setPriority(Thread.NORM_PRIORITY);
        return t;
      }
    

    【讨论】:

      【解决方案3】:

      最简单的解决方案是复制粘贴原始源代码:

      private static class DefaultThreadFactory implements ThreadFactory {
          private static final AtomicInteger poolNumber = new AtomicInteger(1);
          private final ThreadGroup group;
          private final AtomicInteger threadNumber = new AtomicInteger(1);
          private final String namePrefix;
      
          DefaultThreadFactory() {
              SecurityManager s = System.getSecurityManager();
              group = (s != null) ? s.getThreadGroup() :
                                    Thread.currentThread().getThreadGroup();
              namePrefix = "pool-" +
                            poolNumber.getAndIncrement() +
                           "-thread-";
          }
      
          public Thread newThread(Runnable r) {
              Thread t = new Thread(group, r,
                                    namePrefix + threadNumber.getAndIncrement(),
                                    0);
              if (t.isDaemon())
                  t.setDaemon(false);
              if (t.getPriority() != Thread.NORM_PRIORITY)
                  t.setPriority(Thread.NORM_PRIORITY);
              return t;
          }
      }
      

      并添加您想要的更改。为什么没有更简单的方法可以做到这一点,我不知道。我要做的就是更改线程的名称。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-03-11
        • 1970-01-01
        • 1970-01-01
        • 2010-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多