Всегда поддерживать фиксированное количество потоков

1

Я создаю пул фиксированных потоков из службы-исполнителя. Но если возникнет какое-то исключение или ошибка при запуске (ошибка OutOfMemory), поток будет мертв, и количество потоков будет продолжать уменьшаться, и за один раз количество потоков будет равно нулю, что называется убийством беззвучного потока.

Один из способов - поймать бросок (что не является хорошей практикой), чтобы избежать уничтожения потока. Есть ли способ поддерживать постоянное число потоков. Если поток убивает/умирает, то новый поток должен автоматически появляться так, чтобы мы фиксировали количество потоков всегда.

Любые предложения заметны.

  • 0
    Можете ли вы привести пример «тихого» потока? Я не могу воспроизвести это. Я обновил код в этом ответе, чтобы OutOfMemoryError в конце первого Runnable но программа все еще работает нормально - ThreadPoolExecutor просто отбрасывает «старый» поток и создает новый.
  • 0
    @vanOekel Вы уверены, что ThreadPool Executor создает новый, когда старый поток умирает. Я никогда не нахожу это нигде. Любая ссылка действительно будет очень полезна.
Показать ещё 1 комментарий
Теги:
thread-safety
threadpool
threadpoolexecutor

1 ответ

0

В ApiDocs для SingleThreadExecutor указано следующее: "Обратите внимание, что если этот единственный поток завершается из-за сбоя во время выполнения перед завершением работы, новый будет SingleThreadExecutor, если это необходимо для выполнения последующих задач".

Это также относится к ThreadPools с несколькими потоками (см. Демонстрационную программу ниже). Поэтому, если программа не запускает inro реальный OutOfMemoryError (например, не случайный, когда выделен слишком большой байт-массив), тихий поток убивает не произойдет. Если программа работает в реальном OutOfMemoryError то я не думаю, что многое можно сделать: все виды операторов, которые должны быть выполнены (в финальных блоках), могут неожиданно не выполняться из-за нехватки памяти, и это может оставить программу в несогласованное состояние (например, ThreadPool без потоков).

В приведенной ниже демонстрационной программе показаны все задачи, которые выполняются, и имена thead показывают, что новые потоки создаются ThreadPool:

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class SilentKillThread {

public static void main(String[] args) {

    try {
        new SilentKillThread().runTest();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

static int MAX_TASKS = 3;
static long SLEEP_TIME_MS = 400;

AtomicInteger tasksDoneCount = new AtomicInteger();

public void runTest() throws Exception {

    ThreadPoolExecutor tp = new ThreadPoolExecutor(MAX_TASKS, MAX_TASKS,
            60L, TimeUnit.SECONDS,
            new LinkedBlockingQueue<Runnable>());

    for (int i = 0; i < MAX_TASKS; i++) {
        tp.execute(new FailingTask());
    }
    for (int i = 0; i < MAX_TASKS; i++) {
        tp.execute(new SleepingTask());
    }
    tp.shutdown();
    if (tp.awaitTermination(SLEEP_TIME_MS * 4, TimeUnit.MILLISECONDS)) {
        System.out.println("Finished");
    } else {
        System.out.println("Finished but threadpool still active.");
    }
    System.out.println("Tasks done: " + tasksDoneCount.get());
}

class FailingTask implements Runnable {

    @Override 
    public void run() { 
        String tname = Thread.currentThread().getName();
        System.out.println(tname + " Sleeping");
        try { Thread.sleep(SLEEP_TIME_MS); } catch (Exception e) { e.printStackTrace();} 
        int tcount = tasksDoneCount.incrementAndGet();
        System.out.println(tname + " Done sleeping " + tcount);
        throw new OutOfMemoryError();
    }
}

class SleepingTask implements Runnable {

    @Override 
    public void run() { 
        String tname = Thread.currentThread().getName();
        System.out.println(tname + " Sleeping");
        try { Thread.sleep(SLEEP_TIME_MS); } catch (Exception e) { e.printStackTrace();} 
        int tcount = tasksDoneCount.incrementAndGet();
        System.out.println(tname + " Done sleeping " + tcount);
    }
}
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню