Многопоточность - именование потоков и обработка исключений

Каковы предлагаемые способы реализации требований двух потоков в java?

  1. Я хотел бы назвать тему
  2. Я хотел бы, чтобы родительский (или основной) поток знал, есть ли исключения в этом дочернем потоке.

Что касается 2, я понимаю, что наличие будущего объекта было бы лучшим подходом. Итак, для реализации двух вышеуказанных требований ниже приведен код, который я придумал.

class MyRunnable implements Runnable {
  ....
}


MyRunnable myRunnable = new MyRunnable ();
FutureTask futureTask = new FutureTask(myRunnable, null);
Thread myThread = new MyThread(futureTask, "processing-thread");
myThread.start();
try {
   futureTask.get();
} catch (Exception e) {
   throw new RuntimeException(e)
}

Кажется, это много кода для простых вещей. Есть способы лучше?

Примечание. Использование executorService не вариант, поскольку у меня есть потоки, которые не выполняют аналогичные задачи. Также executeorService принимает префикс имени потока вместо имени потока. Я хочу дать каждому потоку уникальное имя.


person Andy Dufresne    schedule 05.06.2013    source источник
comment
Найдите ThreadFactory. Реализуя его, вы можете иметь уникальное именование для каждого нового потока, который вы запрашиваете у него. Вы также можете предоставить его для ExecutorService и, таким образом, переопределить его именование. Что заставляет вас думать, что ExecutorService требует, чтобы задачи были похожими?   -  person Fildor    schedule 05.06.2013
comment
@Fildor - Спасибо за ответ. Как использовать ThreadFactory без использования ExecutorService? Кстати, я думал, что, поскольку ExecutorService называет потоки с помощью соглашения, такого как pool-1-thread-1, по умолчанию он предназначен для отправки аналогичных выполняемых задач. Как отправлять разные потоки и давать им уникальные имена с помощью ExecutorService?   -  person Andy Dufresne    schedule 05.06.2013


Ответы (2)


Использование executeorService не вариант, поскольку у меня есть потоки, которые не выполняют аналогичные задачи.

Я не понимаю, какое это имеет значение.

Также executeorService принимает префикс имени потока вместо имени потока. Я хочу дать каждому потоку уникальное имя.

Так что дайте каждому потоку имя с ThreadFactory. У меня есть класс, который я называю NamedThreadFactory.

Я подозреваю, что вы хотите, чтобы поток отражал то, что делает задача.

Ты можешь это сделать

ExecutorService es = Executors.newSingleThreadExecutor();
es.submit(new Runnable() {
    public void run() {
        Thread.currentThread().setName("Working on task A");
        try {
            System.out.println("Running: "+Thread.currentThread());
        } finally {
            Thread.currentThread().setName("parked worker thread");
        }
    }
});
es.shutdown();

отпечатки

Running: Thread[Working on task A,5,main]

Кстати, нет смысла начинать поток и сразу же ждать его завершения. Вы также можете использовать текущий поток.

person Peter Lawrey    schedule 05.06.2013
comment
ExecutionorService именует потоки по своему собственному соглашению, если экземпляр фабрики потоков не передан. Поэтому вызов Thread.currentThread (). SetName (my-name), я думаю, не сработает. - person Andy Dufresne; 05.06.2013
comment
@AndyDufresne Или вы можете попробовать, посмотрите мой обновленный ответ. Я третий по репутации по Java и первый, кто получил серебряный значок за JVM;) - person Peter Lawrey; 05.06.2013
comment
В порядке. Моя ошибка. Оно работает. Кстати, разве не чисто использовать службу исполнителя для выполнения задач, которые не имеют ничего общего или не похожи? - person Andy Dufresne; 05.06.2013
comment
@AndyDufresne Я бы сказал, что ExecutorService предназначена для выполнения случайных Runnables и Callables, которые могут не иметь ничего общего друг с другом. Он предназначен для агрегирования работы, которая могла быть выполнена большим количеством потоков, в более мелкие пулы потоков. - person Peter Lawrey; 07.06.2013

Для наименования:

ThreadFactory myFactory = new ThreadFactory(){
  @Override public Thread newThread( Runnable r ) {
       return new Thread( r, getName() )
  }

  private int number = 0;

  private String getName(){
      return "MyThread_" + (number++);
  }

}

Есть и другие способы. Лично мне это больше всего нравится.

---РЕДАКТИРОВАТЬ---

Чтобы дать потоку совершенно другие имена, я бы пошел другим путем:

Одна из возможностей - установить имя внутри Runnable: см. Ответ Питера с одним дополнением: вместо фиксированной String вы можете инициализировать переменную-член вашей реализации Runnable перед запуском Thread.

person Fildor    schedule 05.06.2013
comment
Пожалуйста, посмотрите мою правку. Использовать ThreadFactory без Executor просто: вместо new Thread(... вы вызываете myThreadFactory.newThread( myRunnable). - person Fildor; 05.06.2013