简体   繁体   English

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

[英]Why is my multi-threaded application being paused?

My multi-threaded application has a main class that creates multiple threads.我的多线程应用程序有一个创建多个线程的主类。 The main class will wait after it has started some threads.主类将在启动一些线程后等待。 The runnable class I created will get a file list, get a file, and remove a file by calling a web service.我创建的runnable类将通过调用web服务获取文件列表、获取文件和删除文件。 After the thread is done it will notify the main class to run again.线程完成后,它会通知主类再次运行。 My problem is it works for a while but possibly after an hour or so it will get to the bottom of the run method from the output I see in the log and that is it.我的问题是它可以工作一段时间,但可能在一个小时左右后,它会从我在日志中看到的输出到达 run 方法的底部,就是这样。 The Java process is still running but it does not do anything based on what I am looking at in the log. Java 进程仍在运行,但根据我在日志中查看的内容,它没有执行任何操作。

Main class methods:主要类方法:

Main method主要方法

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();
//        }  
}

I originally did the synchronization on the instance but changed it to the method.我最初在实例上进行了同步,但将其更改为方法。 Also no errors are being recorded in the web service log or client log.在 Web 服务日志或客户端日志中也没有记录任何错误。 My assumption is I did the wait and notify wrong or I am missing some piece of information.我的假设是我等待并通知错误,或者我错过了一些信息。

Runnable Thread Code:可运行线程代码:

At the end of the run method在 run 方法结束时

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

The reason I did a wait and notify process because I do not want the main class to run unless there is a need to create another thread.我之所以进行等待和通知过程,是因为我不希望主类运行,除非需要创建另一个线程。

The purpose of the main class is to spawn threads.主类的目的是产生线程。 The class has an infinite loop to run forever creating and finishing threads.该类有一个无限循环来永远运行创建和完成线程。

Purpose of the infinite loop is for continually updating the company list.无限循环的目的是不断更新公司列表。

I'd suggest moving from the tricky wait/notify to one of the higher-level concurrency facilities in the Java platform.我建议从棘手的等待/通知转移到 Java 平台中的高级并发工具之一。 The ExecutorService probably offers the functionality you require out of the box. ExecutorService可能提供您需要的开箱即用的功能。 ( CountDownLatch could also be used, but it's more plumbing) Let's try to sketch an example using your code as template: (也可以使用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() {...}
}

------- edit after comments ------ -------评论后编辑------

If your getCompanies() call can give you all companies at once, and there's no requirement to check that list continuously while processing, you could simplify the process by creating all work items first and submit them to the executor service all at once.如果您的getCompanies()调用可以一次为您提供所有公司,并且不需要在处理时连续检查该列表,您可以通过首先创建所有工作项并将它们一次性提交给执行程序服务来简化流程。

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

The important thing to understand is that the executorService will use the provided collection as an internal queue of tasks to execute.需要理解的重要一点是 executorService 将使用提供的集合作为要执行的内部任务队列。 It takes the first task, gives it to a thread of the pool, gathers the result, places the result in the result collection and then takes the next task in the queue.它接受第一个任务,将其交给池中的一个线程,收集结果,将结果放入结果集合中,然后接受队列中的下一个任务。

If you don't have a producer/consumer scenario (cfr comments), where new work is produced at the same time that task are executed (consumed), then, this approach should be sufficient to parallelize the processing work among a number of threads in a simple way.如果您没有生产者/消费者场景(cfr 评论),即在执行(消耗)任务的同时产生新工作,那么这种方法应该足以并行处理多个线程之间的工作以一种简单的方式。

If you have additional requirements why the lookup of new work should happen interleaved from the processing of the work, you should make it clear in the question.如果您有其他要求,为什么要在工作处理中交错查找新工作,则应在问题中明确说明。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM