Подтвердить что ты не робот

Как указать имя вызываемой теме?

Я выполняю вызываемый объект, используя пул потоков ExecutorService. Я хочу дать название этой теме.

Чтобы быть более конкретным, в более старой версии я сделал это -

Thread thread = new Thread(runnable Task);
thread.setName("My Thread Name");

Я использую имя потока в log4j logging, это помогает во время устранения неполадок. Теперь я переношу свой код с Java 1.4 на Java 1.6. Я написал это (учитывая ниже) - но я не знаю, как назвать имя этой теме.

private final ExecutorService executorPool = Executors.newCachedThreadPool();
Future<String> result = executorPool.submit(callable Task);

Пожалуйста, дайте мне идею дать название этой теме?

4b9b3361

Ответ 1

Вы можете использовать перегруженный метод:

java.util.concurrent.Executors.newCachedThreadPool(ThreadFactory)

который позволяет вам передать

java.util.concurrent.ThreadFactory

который должен позволять вам устанавливать имена потоков через java.util.concurrent.ThreadFactory.newThread(Runnable):

Создает новый Thread. Реализации также могут инициализировать приоритет, имя, статус демона, ThreadGroup и т.д.

Взгляните на java.util.concurrent.Executors.DefaultThreadFactory для реализации по умолчанию.

Добавление

Так как я вижу, что этот поток по-прежнему посещен, Guava (если у вас есть) доступен ThreadFactoryBuilder, который использует необходимость наличия внутреннего анонимного класса и даже позволяет настраивать параметризованные имена для ваших потоков.

Ответ 2

В настоящее время я делаю это примерно так:

    someExecutor.execute(new Runnable() {
        @Override public void run() {
            final String orgName = Thread.currentThread().getName();
            Thread.currentThread().setName(orgName + " - My custom name here");
            try {
                myAction();
            } finally {
                Thread.currentThread().setName(orgName);
            }
        }
    });

Ответ 3

/**
 * The default thread factory
 */
static class DefaultThreadFactory implements ThreadFactory {
    static final AtomicInteger poolNumber = new AtomicInteger(1);
    final ThreadGroup group;
    final AtomicInteger threadNumber = new AtomicInteger(1);
    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;
    }
}

Это оригинальная реализация в Java 1.5.0. Итак, у вас есть имена как pool-x-thread, где x обозначает порядок потока в текущей группе потоков.

Ответ 4

Вы должны быть осторожны при переименовании потоков, когда ваши потоки управляются пулом потоков, поскольку они на самом деле повторно используются для разных задач и после переименования вы можете обнаружить, что имена потоков в ваших журналах не являются иметь какой-то смысл... Чтобы избежать этого нежелательного поведения, вы должны убедиться, что после того, как ваш Runnable/Callable завершит восстановление имени потока,

Один из способов реализации этого - обматывать каждый Runnable/Callable, который выполняется пулом потоков с помощью декоратора, который обрабатывает все необходимые очистки.

Ответ 6

Мне просто нужно было делать то, о чем вы просите, - предоставляя имена моим группам нитей - поэтому, благодаря ответу Andeas, я создал свой собственный ThreadFactory в качестве внутреннего класса для класса, который будет использовать его, копируя Исполнители $DefaultThreadFactory, изменяя 3 строки, добавляя в конструктор параметр "groupname".

    /**
 * A thread factory that names each thread with the provided group name.
 * <p>
 * Except lines with "elarson modified", copied from code 
 * Executors$DefaultThreadFactory -- Doug Lea, Copyright Oracle, et al.
 */
static class GroupNameThreadFactory implements ThreadFactory {
    private String groupname; /* elarson modified */
    private static final AtomicInteger poolNumber = new AtomicInteger(1);
    private final ThreadGroup group;
    private final AtomicInteger threadNumber = new AtomicInteger(1);
    private final String namePrefix;

    GroupNameThreadFactory(String groupname) {
        this.groupname = groupname; /* elarson modified */
        SecurityManager s = System.getSecurityManager();
        group = (s != null) ? s.getThreadGroup() :
                              Thread.currentThread().getThreadGroup();
        namePrefix = "pool-" +
                       this.groupname + /* elarson modified */
                       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;
    }
}

Создание ThreadPool из него выполняется следующим образом.

        ThreadFactory threadfactory = new GroupNameThreadFactory("Monitor");    
    executor = Executors.newFixedThreadPool(NUM_THREADS, threadfactory);

Спасибо пользователю381878 за вопрос, и Андреас за ответ.

Ответ 7

Просто создайте анонимный ThreadFactory для получения службы-исполнителя. ThreadFactory может предоставить имя для потока следующим образом: "Thread A" или "Thread B" (см. Пример).

Затем вызовите вызываемую задачу, используя различные службы-исполнители:

Пример Класс:

открытый класс ThreadTester {

public static void main(String[] args) {
    ThreadTester threadTester = new ThreadTester();
    threadTester.test();
}

private void test() {

    ExecutorService executorservice = Executors.newCachedThreadPool(new ThreadFactory() {

        @Override
        public Thread newThread(Runnable arg0) {
            return new Thread(arg0,"Thread A");
        }
    });

    CallableTask taskA = new CallableTask();
    executorservice.submit(taskA);

    executorservice = Executors.newCachedThreadPool(new ThreadFactory() {

        @Override
        public Thread newThread(Runnable arg0) {
            return new Thread(arg0,"Thread B");
        }
    });
    CallableTask taskB = new CallableTask();
    executorservice.submit(taskB);
}

}

Запрашиваемая задача:

Открытый класс CallableTask реализует Callable {

@Override
public Integer call() throws Exception {
    int sum = 0;

    for(int count=1;count<=30;count++){
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " Count :"+count);
        sum = sum + count;
    }
    System.out.println(Thread.currentThread().getName() + " Sum :"+sum);
    return sum;
}

}

Ответ 8

Один подход, который я использовал, и в моем случае у меня было несколько фьючерсов, которые собирали данные параллельно, контролируемые одним классом. Я подаю несколько заданий и верну их фьючерсы. Я сохраняю будущее на карте со значением в качестве имени задания. Затем, позже, когда я получаю таймаут во всех фьючерсах, у меня есть имя задания с карты. Это не самый гибкий способ, но он работал в моей ситуации.