我的多线程应用程序有一个创建多个线程的主类。主类在启动一些线程后会等待。我创建的可运行类将获取文件列表,获取文件,并通过调用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();
我之所以进行等待和通知过程,是因为我不希望主类运行,除非需要创建另一个线程。
主类的目的是产生线程。该类有一个无限循环,可以永久地创建和完成线程。
无限循环的目的是不断更新公司列表。
答案 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注释),在执行(使用)任务的同时生成新工作,则此方法应足以并行化处理工作。线程数以简单的方式。
如果您有其他要求,为什么新工作的查找应该与处理工作交错进行,您应该在问题中明确说明。