Следующая программа повторяет проблему (я использовал фиксированный пул размера 1, чтобы усугубить проблему)
Код: Выделить всё
public class ThreadPoolTest {
static ExecutorService threadPool=Executors.newFixedThreadPool(1);
//method run by inner callable
public void printText(){
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(ThreadPoolTest.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("Printed from within thread");
}
//method run by outer callable
public void testThreadPool(){
Callable printOnAThread=()->{printText(); return null; };
Future f2=threadPool.submit(printOnAThread);
try {
System.out.println("Called");
f2.get(); //{t.testThreadPool();return null;};
Future f=threadPool.submit(
testCallable
);
try {
f.get();
} catch (InterruptedException | ExecutionException ex) {
Logger.getLogger(ThreadPoolTest.class.getName()).log(Level.SEVERE, null, ex);
throw new RuntimeException("Main thread failed", ex);
}
}
public static void main(String[] args){
testThreadWithinThread();
threadPool.shutdown();
System.out.println("Program exits");
}
}
- Первая тема отправлена. testThreadWithinThread() выполняется
- отправляет вызываемый объект (
Код: Выделить всё
testThreadWithinThread()
)Код: Выделить всё
()->{t.testThreadPool();return null;};
- Отправленный вызываемый объект начинает работать «немедленно»
- t.testThreadPool(); начинает работать
- сам отправляет внутренний вызываемый объект ()->{printText(); вернуть ноль; };
Код: Выделить всё
testThreadPool();
- Внутренний вызываемый объект еще не может быть запущен, поскольку пул потоков несвободен
- достигнут, внешний вызываемый блокируется и ждет. Это освобождает поток в фиксированном пуле.
Код: Выделить всё
f.get();
- Внутренний вызываемый объект теперь выполняется до завершения.
- больше не блокируется, внешний вызываемый объект выполняется до завершения.
Код: Выделить всё
f2.get();
Шаги 1–6 происходят, как я и ожидал, однако в точке 7, когда внешний вызываемый объект блокируется; по какой-то причине поток не освобождается и программа зависает.
Вопрос
Почему программа зависает на этом этапе? Есть ли способ безопасно отправлять вызываемые объекты из вызываемых объектов?
Подробнее здесь: https://stackoverflow.com/questions/236 ... the-progra