监视长时间运行的线程

时间:2014-05-31 22:29:46

标签: java multithreading command-line

我接管了一个Java命令行程序,该程序打开文件的zip文件,并使用最多8个线程(每个文档一个线程)处理这些文档,以处理文档并将其数据加载到数据库中( Inserter类的实例)。以前的开发人员没有以任何方式编写代码来管理这些线程,而且我一直试图找到一些高效的方法来监控并干净地关闭线程以及线程池和计时器。

我可以在一个连续的循环中监视线程,但是这会占用大量的CPU而且似乎错了。但是当我尝试运行TimerTask来检查线程时,即使完成所有工作,它似乎永远不会退出。据我所知,这应该有效。我做错了什么?

/*
NOTES:
timer is a java.util.Timer
pool is a Executors.newFixedThreadPool(8);
_listUncompressDirectories is a ConcurrentLinkedQueue<List<File>>
inserters is a ConcurrentMap<Integer, Inserter>
tasks is a ConcurrentMap<Integer, Future>
*/
            // Code isolated from its method.
            for (int i = 0; i <= 7; i++) {
                if (_listUncompressDirectories.isEmpty()) {
                    break;
                }
                pool.submit(new Inserter());
                inserters.put(i, new Inserter());
                tasks.put(i, pool.submit(inserters.get(i)));
            }
            timer.schedule(new MonitorTask(), 90 * 1000); //delay in milliseconds


/**
 * Thread pool monitor task.
 */
private class MonitorTask extends TimerTask {
    @Override
    public void run() {
        if (tasks.isEmpty()) {
            applicationShutdown();
        }
        else {
            for (final int i : tasks.keySet()) {
                if (tasks.get(i).isDone()) {
                    tasks.get(i).cancel(true);
                    inserters.remove(i);
                    tasks.remove(i);
                }
            }
            if (tasks.isEmpty()) {
                applicationShutdown();
            }
        }
    }
}
private static void applicationShutdown () {
    pool.shutdownNow();
    timer.cancel();
    timer.purge();
    System.exit(-1);
}

2 个答案:

答案 0 :(得分:0)

I can monitor the threads in a continuous loop, but that uses up a lot of CPU 
and just seems wrong. 

您的想法不一定错,也不一定使用高CPU。这是一个使用低CPU的示例。

    Thread t = new Thread(new Runnable(){
        public void run() {
            while(<isAppStillRunningBoolean>) {
            try {
                  doOtherThreadsMonitoringAndHouskeeping();
                  Thread.sleep(52);
            } catch (Exception e) {
                e.printStackTrace();
                break;
            }
            }
        }});
    t.setDeamon(true);
    t.start();

答案 1 :(得分:0)

我犯了一个错误。计时器代码应如下所示:

timer.schedule(new MonitorTask(), 90 * 1000, 90 * 1000);

延迟90秒,每90秒重新运行一次。

发生的事情是applicationShutdown()方法从未被调用,因为计时器任务只运行一次而且从未再次检查过线程,因此线程池只是在完成所有工作后就坐在那里。