【问题标题】:Java thread stops working and no Exception or Throwable is thrownJava 线程停止工作并且没有抛出异常或 Throwable
【发布时间】:2012-10-19 22:25:48
【问题描述】:

我通常用大约 4 个线程运行我的程序,并且在程序运行后 1 小时到 10 小时之间的任何地方,一些线程只是停止并且什么也不做,我的程序围绕 Exception 和 Throwable 块,我也有一个 uncaughtException线程并且没有任何关于任何错误的信息添加到我的日志文件中。如何找到导致线程停止的原因?

编辑

这是我的代码的基本结构

下面是设置 uncaughtException 块的代码

                newThread.setName("Thread" + totalNumberOfThreads);
                newThread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler()
                {
                    @Override
                    public void uncaughtException(Thread t, Throwable e)
                    {
                        Main.logger.info("ERROR! An exception occurred in " + t.getName() + ". Cause: " + e.getMessage());
                    }
                });
                newThread.start();

这是线程的基本结构

@Override
public void run()
{               
  while (true)
  {
    try
    {               
      //a long section of code
    }
    catch (Exception e)
    {
      e.printStackTrace();
      Main.logger.info(threadName + ": " + e);
    }
    catch (Throwable t)
    {
      Main.logger.info(threadName + ": " + "Throwable: " + t);
    }
    finally
    {      
      //some code to close connections.. ect..
    }
  } // end while
}

【问题讨论】:

  • Deadlocks 是直接嫌疑人。确定程序是否会有一个可能非常棘手。程序在单线程运行时工作正常吗?你在线程之间使用什么同步?
  • 你是什么意思,你有“线程的 uncaughtException”?
  • 在启动线程之前我有 newThread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler(){ @Override public void uncaughtException(Thread t, Throwable e) { Main.logger.info("ERROR!发生异常在 " + t.getName() + "。原因:" + e.getMessage()); } });
  • 不幸的是,我不能粘贴很长的整个代码,而且我不拥有代码,我只是在处理它,但我已经编辑了我的问题以显示程序的结构.
  • @Arya:我不明白你为什么认为这是一个抛出的异常——如果没有显示异常?需要详细说明吗? :|

标签: java multithreading


【解决方案1】:

如何找到导致线程停止的原因?

你知道线程已经停止了吗?如前所述,它们可能会被阻止。您可以使用jstack 来查看它们是否处于活动状态,或者为了更仔细地检查,在启用远程调试的情况下启动程序,并在您觉得它们已停止时附加调试器。

【讨论】:

    【解决方案2】:

    您可以尝试在调试器中运行程序,这样您就可以检查线程的状态。

    您还可以使用 Java 中的内置 Ctrl-BreakCtrl-\机制 - 请参阅 Troubleshooting Hanging or Looping Processes,这将导致 HotSpot VM 打印线程转储,包括线程状态。

    【讨论】:

    • 使用调试器运行很少能解决同步错误。见Heisenbug
    • 你怎么知道这是一个同步错误?
    • 症状是死锁:4 threads and anywhere between 1 hour to 10 hours after the program is running some threads just stop and do nothing .... and nothing gets added to my log files about any errors。它只是尖叫死锁
    • YMMV。我已经解决了调试器中的几个同步问题。这取决于它是调试器可能影响的微妙时序问题,还是无论确切时序如何迟早都会可靠发生的问题。
    【解决方案3】:

    问题只是尖叫DeadLock - 它显示了一个人的所有典型症状。

    死锁是指线程 A 等待线程 B 完成并释放一些资源(锁),而线程 B 等待线程 A 完成并释放一些资源。
    More information on deadlocks can be found in the java tutorial

    这会导致两个线程都停止执行并且什么都不等待。

    在某些情况下,查找程序是否确实存在死锁可能非常棘手,即使在使用旨在检测死锁的程序时,使用该程序也可以暂时“解决问题”。更多详情请见Heisenbug

    有时(但并非总是)检测死锁的最佳方法是查看程序的抽象,并尝试检查线程之间的所有依赖项 - 并查看可能发生依赖项冲突的位置。

    附:另一个常见的同步问题是Data Race

    【讨论】:

    • 对线程使用 join() 方法时是否会发生死锁?因为我没有使用 .join() 并且我只是阅读了链接并且我也没有使用同步。我正在使用 HTMLUnit 库会导致这个问题吗?
    • @Arya:当您使用join()synchronized 关键字,或一些阻塞数据结构(如ConcurrentSkipListMap),或几乎所有不同线程之间的同步时,它们可能会发生。
    • 我在你的评论加载之前编辑了我的最后一条评论。如果我使用的库有死锁问题,我能做的不多吗?
    • @Arya:我不知道不熟悉那个库——这真的取决于你如何使用所有东西。线程之间有共享数据吗? (他们是在写入同一个资源吗?从同一个资源读取?互相发送数据?)
    • @Arya 另外一个可能的问题是,如果您的线程写给了不是close()d 的作者。是那里的问题吗?
    【解决方案4】:

    首先,我会研究 ExecutorService 并将您的代码分解为 Callable。这将允许您在能够返回值或让异常上升的线程中运行它。然后,如果出现问题,您可以重新启动它。

    每当代码捕获 Exception 和/或 Throwable 时,就会产生很大的代码异味。应抛出已检查异常之外的任何异常。如果您使用上面提到的可调用模式,您可以检查您得到的内容、记录它并重新启动(如有必要)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-28
      • 1970-01-01
      • 1970-01-01
      • 2018-09-19
      • 2016-07-01
      • 2018-09-18
      • 2019-08-19
      • 2012-10-11
      相关资源
      最近更新 更多