2

LMAX ディストラプターを使用して、プログラムの 1 つによって生成されたコンテンツをバッファリングし、それらをレコードのバッチとして別のプログラムに公開しようとしました (まあ、まだ消費者のバッチ処理の部分を完了できません)。ただし、レコードのバッチ処理を使用しなくても、正常に機能します。しかし、私の問題は、私が使用したにもかかわらず

`disruptor.shutdown()` and  `executorService.shutdownNow()`

例の 1 つに示されているように、プログラムの実行は停止しません。これらのメソッドの下のステートメントも実行します。印刷するとき

executorService.isShutdown();

true を返します。誰かがこれで私を助けることができます...

編集

"pool-1-thread-1" prio=10 tid=0x00007f57581b9800 nid=0x1bec waiting on condition [0x00007f573eb0d000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x00000000d9110148> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
    at com.lmax.disruptor.BlockingWaitStrategy.waitFor(BlockingWaitStrategy.java:45)
    at com.lmax.disruptor.ProcessingSequenceBarrier.waitFor(ProcessingSequenceBarrier.java:55)
    at com.lmax.disruptor.BatchEventProcessor.run(BatchEventProcessor.java:123)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)
4

2 に答える 2

3

私に役立ついくつかのヒント:

1. ExecutorService スレッドにデーモン フラグを設定する

ThreadFactory(またはGuavaの)でこれを行いThreadFactoryBuilderます。

例:

final ThreadFactory threadFactory = 
    new ThreadFactory() {
    @Override
    public Thread newThread(Runnable r) {
        final ThreadFactory threadFactory = Executors.defaultThreadFactory();
        final Thread thread = threadFactory.newThread(r);
        thread.setDaemon(true);
        return thread;
    }
};
final ExecutorService executorService =
    Executors.newFixedThreadPool(threadCount, threadFactory);

2. シャットダウン命令

  1. Disruptor.shutdown(long, TimeUnit)
  2. Disruptor.halt()
  3. ExecutorService.shutdown()
  4. ExecutorService.awaitTermination(long, TimeUnit)

せっかちなシャットダウンの例:

try {
    disruptor.shutdown(0, TimeUnit.NANOSECONDS);
    // if shutdown is successful:
    // 1. exception is not thrown (obviously)
    // 2. Disruptor.halt() is called automatically (less obvious)
}
catch (TimeoutException e) {
    disruptor.halt();
}
executorService.shutdown();
executorService.awaitTermination(0, TimeUnit.NANOSECONDS);

3.シャットダウンフックを使用する

これらは が呼び出された場合でもSystem.exit(int)呼び出されますが、JVM がSIGKILL(または非 POSIX プラットフォームでは同等のもので) 強制終了された場合は呼び出されません。

Runtime.getRuntime()
    .addShutdownHook(
        new Thread(
            () -> {
                // shutdown here
            }));
于 2015-12-21T12:19:17.380 に答える
1

Java プロセスは、すべてのスレッド (非デーモン スレッド) が終了したときにのみ停止します。おそらくいくつかのスレッドがまだ実行中であり、おそらくロックされているか、ループしている可能性があります。

どのスレッドがまだ実行されているかを確認するには、jdk-tools を使用できます。

jps実行中の Java プロセスの ID を取得するために使用します。

C:\DVE\jdk\jdk8u45x64\jdk1.8.0_45\bin>jps
4112 TestExMain

プログラムの正しい ID を使用して、次のコマンドを使用しますjstack

C:\DVE\jdk\jdk8u45x64\jdk1.8.0_45\bin>jstack 4112
2015-09-17 09:12:45
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.45-b02 mixed mode):

"Service Thread" #9 daemon prio=9 os_prio=0 tid=0x000000001d208800 nid=0x1b7c runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"main" #1 prio=5 os_prio=0 tid=0x0000000002260800 nid=0x1324 waiting on condition [0x000000000224f000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at com.example.TestExMain.main(TestExMain.java:8)

たとえば、ここにService Threadデーモンであるスレッドが表示されます。このスレッドは、プログラムのシャットダウンを停止しません。Thread main はデーモン スレッドではありません。Java プロセスは、このスレッドが終了するまで待機してから停止します。スレッドごとに、スタック トレースが表示されます。これにより、スレッドが実行されないようにする可能性のあるコードを見つけることができます。


そこにある特定のスレッドが何らかの形でロックされています(理由はわかりませんが、wait()呼び出し、synchronizeブロック、またはその他のロックメカニズムである可能性があります)。呼び出したときにそのスレッドが停止しない場合はdisruptor.shutdown()、使用しているライブラリのバグである可能性があります。

于 2015-09-17T07:18:01.223 に答える