2

我一直在尝试使用 LMAX 干扰器来缓冲我的一个程序产生的内容,并将它们作为一批记录发布到另一个程序(我仍然无法完成消费者批处理部分)。但即使不使用记录的批处理,它也可以正常工作。但我的问题是即使我使用调用

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

正如在其中一个示例中给出的那样,它不会停止执行程序。它甚至会在这些方法下面执行语句。当我打印

executorService.isShutdown();

它返回真。有人可以帮我弄这个吗...

编辑

"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-Process 将等待该线程完成,然后再停止。对于每个线程,您将看到一个堆栈跟踪,即线程所在的位置——您可以找到可能阻止线程运行的代码。


你在那里的那个特定线程以某种方式被锁定(我不知道为什么,它可能是一个wait()调用、一个synchronize块或其他一些锁定机制)。当你调用它时该线程没有停止时,disruptor.shutdown()它可能是你使用的那个库中的一个错误。

于 2015-09-17T07:18:01.223 回答