为什么我的多线程应用程序被暂停?

时间:2012-11-22 18:50:37

标签: java multithreading wait notify thread-synchronization

我的多线程应用程序有一个创建多个线程的主类。主类在启动一些线程后会等待。我创建的可运行类将获取文件列表,获取文件,并通过调用Web服务删除文件。线程完成后,它将通知主类再次运行。我的问题是它工作了一段时间,但可能在一个小时左右后,它将从我在日志中看到的输出到达run方法的底部,就是这样。 Java进程仍在运行,但根据我在日志中看到的内容,它没有做任何事情。

主要类方法:

主要方法

while (true) {

    // Removed the code here, it was just calling a web service to get a list of companies

    // Removed code here was creating the threads and calling the start method for threads

    mainClassInstance.waitMainClass();
}

public final synchronized void waitMainClass() throws Exception {
//        synchronized (this) {
           this.wait();
//        }  
}

public final synchronized void notifyMainClass() throws Exception {
//        synchronized (this) {
           this.notify();
//        }  
}

我最初在实例上进行了同步,但将其更改为方法。此外,Web服务日志或客户端日志中不会记录任何错误。我的假设是我做了等待并通知错误或者我错过了一些信息。

可运行的线程代码:

在运行方法结束时

// This is a class member variable in the runnable thread class
mainClassInstance.notifyMainClass();

我之所以进行等待和通知过程,是因为我不希望主类运行,除非需要创建另一个线程。

主类的目的是产生线程。该类有一个无限循环,可以永久地创建和完成线程。

无限循环的目的是不断更新公司列表。

1 个答案:

答案 0 :(得分:2)

我建议从棘手的等待/通知转移到Java平台中的一个更高级别的并发工具。 ExecutorService可能提供开箱即用的功能。 (CountDownLatch也可以使用,但它更管道) 让我们尝试使用您的代码作为模板绘制一个示例:

ExecutorService execSvc = Executors.newFixedThreadPool(THREAD_COUNT);

while (true) {

    // Removed the code here, it was just calling a web service to get a list of companies
    List<FileProcessingTask> tasks = new ArrayList<FileProcessingTask>();
    for (Company comp:companyList) {
        tasks.add(new FileProcessingTask(comp));
    }
    List<Future<FileProcessingTask>> results = execSvc.invokeAll(tasks); // This call will block until all tasks are executed.
    //foreach Future<FileProcessingTask> in results: check result
}

class FileProcessingTask implements Callable<FileResult> {  // just like runnable but you can return a value -> very useful to gather results after the multi-threaded execution
    FileResult call() {...}
}

-------评论后编辑------

如果您的getCompanies()电话可以立即为您提供所有公司,并且在处理过程中无需连续检查该列表,您可以先创建所有工作项并将其提交给执行者服务,从而简化流程马上。

List<FileProcessingTask> tasks = new ArrayList<FileProcessingTask>();
    for (Company comp:companyList) {
        tasks.add(new FileProcessingTask(comp));
    }

要理解的重要一点是executorService将使用提供的集合作为要执行的任务的内部队列。它接受第一个任务,将它提供给池的一个线程,收集结果,将结果放在结果集合中,然后在队列中接受下一个任务。

如果您没有生产者/消费者场景(cfr注释),在执行(使用)任务的同时生成新工作,则此方法应足以并行化处理工作。线程数以简单的方式。

如果您有其他要求,为什么新工作的查找应该与处理工作交错进行,您应该在问题中明确说明。