[java] ExecutorService의 이름 지정 스레드 및 스레드 풀

Executor프레임 워크 를 활용하는 응용 프로그램이 있다고 가정 해 보겠습니다.

Executors.newSingleThreadExecutor().submit(new Runnable(){
    @Override
    public void run(){
        // do stuff
    }
}

이 응용 프로그램을 디버거에서 실행하면 다음과 같은 (기본) 이름으로 스레드가 생성됩니다 Thread[pool-1-thread-1]. 보시다시피, 이것은별로 유용 Executor하지 않으며 내가 알 수있는 한 프레임 워크는 작성된 스레드 또는 스레드 풀의 이름을 쉽게 지정할 수 있는 방법을 제공하지 않습니다.

그렇다면 스레드 / 스레드 풀의 이름을 어떻게 제공합니까? 예를 들어 Thread[FooPool-FooThread].



답변

를 제공 할 ThreadFactorynewSingleThreadScheduledExecutor(ThreadFactory threadFactory)있습니다. 팩토리는 스레드 작성에 대한 책임이 있으며 이름을 지정할 수 있습니다.

Javadoc 을 인용하려면 :

새 스레드 만들기

를 사용하여 새 스레드가 생성됩니다 ThreadFactory. 다르게 지정되지 않으면, Executors.defaultThreadFactory()스레드가 ThreadGroup동일한 NORM_PRIORITY우선 순위 및 비 데몬 상태에 있도록 스레드를 작성 하는 a 가 사용됩니다 . 다른을 제공 ThreadFactory하면 스레드의 이름, 스레드 그룹, 우선 순위, 데몬 상태 등을 변경할 수 있습니다. ThreadFactory에서 from을 반환하여 요청시 스레드를 작성하지 못하면 newThread실행 프로그램이 계속되지만 태스크를 실행할 수 없습니다.


답변

구아바에는 거의 항상 필요한 것이 있습니다 .

ThreadFactory namedThreadFactory = 
  new ThreadFactoryBuilder().setNameFormat("my-sad-thread-%d").build()

그리고 당신에게 전달하십시오 ExecutorService.


답변

고유 한 스레드 팩토리를 제공하여 적절한 이름의 스레드를 작성할 수 있습니다. 예를 들면 다음과 같습니다.

class YourThreadFactory implements ThreadFactory {
   public Thread newThread(Runnable r) {
     return new Thread(r, "Your name");
   }
 }

Executors.newSingleThreadExecutor(new YourThreadFactory()).submit(someRunnable);


답변

스레드가 실행되는 동안 나중에 스레드 이름을 변경할 수도 있습니다.

Thread.currentThread().setName("FooName");

예를 들어 다른 유형의 작업에 동일한 ThreadFactory를 사용하는 경우 관심이 될 수 있습니다.


답변

BasicThreadFactory아파치 평민 – 랭에서 또한 명명 동작을 제공하는 데 유용합니다. 익명의 내부 클래스를 작성하는 대신 Builder를 사용하여 원하는대로 스레드 이름을 지정할 수 있습니다. 다음은 javadocs의 예입니다.

 // Create a factory that produces daemon threads with a naming pattern and
 // a priority
 BasicThreadFactory factory = new BasicThreadFactory.Builder()
     .namingPattern("workerthread-%d")
     .daemon(true)
     .priority(Thread.MAX_PRIORITY)
     .build();
 // Create an executor service for single-threaded execution
 ExecutorService exec = Executors.newSingleThreadExecutor(factory);


답변

Spring을 사용 CustomizableThreadFactory하는 경우 스레드 이름 접두사를 설정할 수 있습니다.

예:

ExecutorService alphaExecutor =
    Executors.newFixedThreadPool(10, new CustomizableThreadFactory("alpha-"));

또는 -를 ExecutorService사용하여 Spring bean으로 만들 수 있으며 ThreadPoolExecutorFactoryBean스레드는 모두 beanName-접두어 로 이름이 지정됩니다 .

@Bean
public ThreadPoolExecutorFactoryBean myExecutor() {
    ThreadPoolExecutorFactoryBean executorFactoryBean = new ThreadPoolExecutorFactoryBean();
    // configuration of your choice
    return executorFactoryBean;
}

위의 예에서 스레드 이름은 myExecutor-접두사 로 지정됩니다 . 당신은 다른 값 (예.에 명시 적으로 접두사를 설정할 수 있습니다 "myPool-"설정하여) executorFactoryBean.setThreadNamePrefix("myPool-")공장 콩에.


답변

Oracle에는이를 위한 공개 RFE 가 있습니다 . 오라클 직원의 의견으로는 문제를 이해하지 못하고 해결되지 않는 것 같습니다. JDK에서 지원하기가 간단하지만 (이전 버전과의 호환성을 유지하지 않고) RFE가 오해하는 것은 부끄러운 일입니다.

지적했듯이 자신의 ThreadFactory 를 구현해야합니다 . 이 목적으로 Guava 또는 Apache Commons를 가져 오지 않으려면 여기에 ThreadFactory사용할 수 있는 구현을 제공하십시오 . 스레드 이름 접두어를 “pool”이외의 것으로 설정하는 기능을 제외하고는 JDK에서 얻는 것과 정확히 유사합니다.

package org.demo.concurrency;

import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * ThreadFactory with the ability to set the thread name prefix.
 * This class is exactly similar to
 * {@link java.util.concurrent.Executors#defaultThreadFactory()}
 * from JDK8, except for the thread naming feature.
 *
 * <p>
 * The factory creates threads that have names on the form
 * <i>prefix-N-thread-M</i>, where <i>prefix</i>
 * is a string provided in the constructor, <i>N</i> is the sequence number of
 * this factory, and <i>M</i> is the sequence number of the thread created
 * by this factory.
 */
public class ThreadFactoryWithNamePrefix implements ThreadFactory {

    // Note:  The source code for this class was based entirely on 
    // Executors.DefaultThreadFactory class from the JDK8 source.
    // The only change made is the ability to configure the thread
    // name prefix.


    private static final AtomicInteger poolNumber = new AtomicInteger(1);
    private final ThreadGroup group;
    private final AtomicInteger threadNumber = new AtomicInteger(1);
    private final String namePrefix;

    /**
     * Creates a new ThreadFactory where threads are created with a name prefix
     * of <code>prefix</code>.
     *
     * @param prefix Thread name prefix. Never use a value of "pool" as in that
     *      case you might as well have used
     *      {@link java.util.concurrent.Executors#defaultThreadFactory()}.
     */
    public ThreadFactoryWithNamePrefix(String prefix) {
        SecurityManager s = System.getSecurityManager();
        group = (s != null) ? s.getThreadGroup()
                : Thread.currentThread().getThreadGroup();
        namePrefix = prefix + "-"
                + poolNumber.getAndIncrement()
                + "-thread-";
    }


    @Override
    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;
    }
}

당신이 그것을 사용하고 싶을 때, 당신은 모든 Executors방법이 당신 자신을 제공 할 수 있다는 사실을 이용합니다 ThreadFactory.

    Executors.newSingleThreadExecutor();

쓰레드가 명명 된 곳에서 ExecutorService를 제공 pool-N-thread-M하지만

    Executors.newSingleThreadExecutor(new ThreadFactoryWithNamePrefix("primecalc"));

당신은 스레드의 이름을 지정하는 ExecutorService를 얻을 수 있습니다 primecalc-N-thread-M. 짜잔!