0

我有一台运行 CentOS 5.9、Apache-Tomcat 5.5.36 的专用服务器。我编写了一个 JAVA Web 应用程序,它每分钟运行一次以从多个传感器收集数据。我正在使用 ScheduledExecutorService 来执行线程。(每个传感器每分钟一个线程,可以有一百多个传感器)线程的流量是

  1. 从数据库中收集传感器信息。
  2. 向仪器发送命令以收集数据。
  3. 使用数据值更新数据库。

还有另一个应用程序每分钟检查一次数据库并将警报发送给用户(如果需要)。我已经使用 jvisualVM 监控了应用程序,我找不到任何内存泄漏。对于每个线程。应用程序工作正常,但一段时间后(24 小时 - 48 小时),应用程序停止工作。我无法找出问题可能是什么,是服务器配置问题,线程太多还是什么?

有谁知道可能出了什么问题,或者有没有人做过思考类的工作?请帮忙,谢谢

更新:包括代码

public class Scheduler {
       private final ScheduledExecutorService scheduler = 
          Executors.newScheduledThreadPool(1);
       public void startProcess(int start) {
           final Runnable uploader = new Runnable() {
            @SuppressWarnings("rawtypes")
            public void run() 
            { 
                //Select data from the database
                ArrayList dataList = getData();
                for(int i=0;i<dataList.size();i++)
                {
                    String args = dataList.get(i).toString();
                    ExecutorThread comThread = new ExecutorThread(args...);
                    comThread.start();
                }
            }
        };
        scheduler.scheduleAtFixedRate(uploader, 0, 60 , TimeUnit.SECONDS);
       }
    }

public class ExecutorThread extends Thread {

    private variables...
    public CommunicationThread(args..)
    {
        //Initialise private variable
    }

    public void run()
    {
        //Collect data from sensor
        //Update Database
    }
}
4

2 回答 2

1

注意Javadoc中这句无害的语句ScheduledExecutorService.schedule...

如果任务的任何执行遇到异常,则后续执行将被抑制。

这意味着,如果您Exception在某个时候遇到 a 并且不处理它,Exception则会传播到该中ScheduledExecutorService并且它将杀死您的任务。

为了避免这个问题,你需要确保整个 Runnable包裹在 atry...catchExceptions保证永远不会被处理。

您还可以扩展ScheduledExecutorService(也在javadoc中提到)来处理未捕获的异常:-

final ScheduledExecutorService ses = new ScheduledThreadPoolExecutor(10){

    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        super.afterExecute(r, t);
        if (t == null && r instanceof Future<?>) {
            try {
                Object result = ((Future<?>) r).get();
            } catch (CancellationException ce) {
                t = ce;
            } catch (ExecutionException ee) {
                t = ee.getCause();
            } catch (InterruptedException ie) {
                Thread.currentThread().interrupt(); // ignore/reset
            }
        }
        if (t != null) {
            System.out.println(t);
        }
    }
};

这里的afterExecute方法很简单System.out.printlnThrowable但它可以做其他事情。提醒用户、重启任务等...

于 2013-04-15T09:09:32.553 回答
1

没有代码不能说太多,但您需要确保您的线程始终正确退出 - 不会在任何异常时挂在内存中,关闭与数据库的连接等。

此外,为了监视您的应用程序,您可以每隔一段时间进行一次线程转储,以查看应用程序生成了多少线程。

另一个建议是将 Tomcat 配置为在 OutOfMemoryError 上进行堆转储。如果这是一个问题,您将能够分析是什么填满了内存

于 2013-04-15T08:54:25.147 回答