Javaではメインスレッドが終了してもプログラムは終了しませんよ
はい、今日のバグでした。
だいたいこんなコード
final ExecutorService executor = Executors.newFixedThreadPool(50); try { searchHoge(new HogeCallback() { public void call(Hoge hoge) { executor.execute(new HogeThread(hoge)); } }); } catch(Exception e) { e.printStackTrace(); } executor.shutdown(); try { executor.awaitTermination(30, TimeUnit.MINUTES); } catch (InterruptedException e) {}
作っていたプログラムでは、全てのデータを探すのを待ってからだと効率が悪いので
- 見つかるたびにHogeCallbackにデータを返す
- データは別スレッドで処理する
という実装にしていた。
で、何に引っかかったかというと、searchHogeの処理はtry - catchをしているんだけど、catchをExceptionで指定していたのでError系(今回はOutOfMemoryError)がスルーされていた。そのため、executor.shutdown()が呼ばれずメインスレッドが終了した後も、executorは永久に来ない仕事を待ち続けていたため、プロセスは終了しなかった、と。
今日の教訓。
executorはいつでもfinallyで書く癖を付けた方がいい。
以下、Javaでメインスレッドが終了してもプログラムが終了しない検証。
Test.java
public class Test { public static void main(String[] args) { new Thread() { public void run() { try { Thread.sleep(10 * 1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("thread end."); } }.start(); System.out.println("main end."); } }
ちゃんと"thread end."が出力された後にプログラムが終了する。
ちなみにRubyの場合。
test.rb
Thread.new do sleep 10 puts 'thread end.' end puts 'main end.'
'thread end.'は出力されずに終わる。