2012-11-22 85 views
1

我的多线程应用程序有一个创建多个线程的主类。主类将在启动一些线程后等待。我创建的可运行类将获得文件列表,获取文件以及通过调用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服务日志或客户端日志中也没有记录错误。我的假设是我做了等待,并通知错误或我错过了一些信息。

运行的线程代码:

在run方法结束

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

我之所以做了观望,因为我不想让主类运行,除非有必要通知过程创建另一个线程。

主要类的目的是产生线程。这个类有一个无限循环来永远创建和完成线程。

无限循环的目的是不断更新公司名单。

+0

您是否添加了任何类型的日志以了解发生了什么? –

+0

请注意,只有在有线程在等待的情况下,通知才有效。如果您的主线程还没有完全等待,通知将落在地面上。 –

+3

你可能会用信号量做得更好。 –

回答

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注释),在执行任务(消耗)的同时生成新工作,则此方法应足以并行处理工作一个简单的方法的线程数量。

如果您有额外的要求,为什么新工作的查找应该与工作处理交错发生,您应该在问题中说清楚。

+0

使用此解决方案,我不希望等待所有线程完成,因为一个线程可能需要10秒钟,而另一个线程需要3分钟,这取决于要处理的文件数量。 – ColinMc

+0

@ user1750090我明白了。唤醒主线程的作用是什么?要找到更多的工作要做,并开始一个新的线程?你有没有像一个线程正在寻找工作要做,而多个线程正在处理该工作? – maasg

+0

唤醒主线程的作用是在完成一个线程时创建更多的线程。基本上它会为每个公司创建一个线程来处理文件,当一个公司完成后,它将返回到主线程并创建另一个公司线程来处理。不,我没有一个线程在多线程处理工作时正在寻找工作。我拥有的唯一线程是产生公司线程和公司线程进行文件处理的主线程。 – ColinMc

相关问题