简体   繁体   English

Java异步执行使CPU增加100%

[英]Java asynchronous execution increases CPU 100%

Introduction: 介绍:

I've developed a class which would accept number of Tasks , execute them in parallel and await for results particular amount of time. 我已经开发了一个类,该类可以接受许多Tasks ,并行执行它们,并等待特定时间的结果。 If some of the tasks failed to finish by given timeout it will interrupt entire execution and return only available results. 如果某些任务未能在给定的超时时间内完成,它将中断整个执行并仅返回可用结果。

Issue: 问题:

All works fine at the beginning but after some time CPU usage increases until 100% and application obviously fails to response. 一切在开始时都可以正常工作,但是一段时间后,CPU使用率会增加,直到100%,并且应用程序显然无法响应。

Could you please try to help me find an issue or suggest better solution how I could achieve the same goal? 您能否尝试帮助我找到问题或提出更好的解决方案,以实现同一目标?

Code: 码:

TaskService.java TaskService.java

public abstract class TaskService {

    private static final org.slf4j.Logger InfoLogger = LoggerFactory.getLogger("InfoLogger");
    private static final org.slf4j.Logger ErrorLogger = LoggerFactory.getLogger("ErrorLogger");

    @Autowired
    private TimeLimiter timeLimiter;


    public List<TaskResult> execute(TaskType taskType, TimeUnit timeUnit, long timeout, final Task... tasks){

        final List<TaskResult> taskResultsStorage = new ArrayList<>();
        try {
            timeLimiter.callWithTimeout(new Callable<List<TaskResult>>() {
                @Override
                public List<TaskResult> call() throws Exception {
                    return run(taskResultsStorage, tasks);
                }
            }, timeout, timeUnit, true);

        } catch (UncheckedTimeoutException e) {
            String errorMsg = String.format("Time out of [%s] [%s] has been exceeded for task type:[%s]", timeout, timeUnit.name(), taskType.name());
            ErrorLogger.error(errorMsg, e);
        } catch (Exception e) {
            String errorMsg = String.format("Unexpected error for task type:[%s]", taskType.name());
            ErrorLogger.error(errorMsg, e);
        }

        return taskResultsStorage;
    }



    protected abstract List<TaskResult> run(List<TaskResult> taskResults,Task... tasks) throws ExecutionException, InterruptedException;

}

AsynchronousTaskService.java AsynchronousTaskService.java

public class AsynchronousTaskService extends TaskService {


    private CompletionService<TaskResult> completionService;

    public AsynchronousTaskService(ThreadExecutorFactory threadExecutorFactory){
        this.completionService = new ExecutorCompletionService<TaskResult>(threadExecutorFactory.getExecutor());
    }


    @Override
    protected List<TaskResult> run(List<TaskResult> resultStorage, Task... tasks) throws ExecutionException, InterruptedException {

        List<Future<TaskResult>> futureResults = executeTask(tasks);
        awaitForResults(futureResults, resultStorage);
        return resultStorage;
    }


    private List<Future<TaskResult>> executeTask(Task... tasks){

        List<Future<TaskResult>> futureTaskResults = new ArrayList<>();
        if(tasks!=null) {
            for (Task task : tasks) {
                if (task != null) {
                    futureTaskResults.add(completionService.submit(task));
                }
            }
        }
        return futureTaskResults;
    }

    private void awaitForResults(List<Future<TaskResult>> futureResults, List<TaskResult> resultStorage) throws ExecutionException, InterruptedException {

        int submittedTasks = futureResults.size();
        int taskCompleted = 0;
        if(futureResults != null){
            while(taskCompleted < submittedTasks){
                Iterator<Future<TaskResult>> it = futureResults.iterator();
                while(it.hasNext()){
                    Future<TaskResult> processingTask = it.next();
                    if(processingTask.isDone()){
                        TaskResult taskResult = processingTask.get();
                        resultStorage.add(taskResult);
                        it.remove();
                        taskCompleted++;
                    }
                }
            }
        }
    }
}

ThreadExecutorFactory.java ThreadExecutorFactory.java

@Component
public class ThreadExecutorFactory {


    private int THREAD_LIMIT = 100;
    private final Executor executor;

    public ThreadExecutorFactory() {
        executor = Executors.newFixedThreadPool(THREAD_LIMIT,
                new ThreadFactory() {
                    public Thread newThread(Runnable r) {
                        Thread t = new Thread(r);
                        t.setDaemon(true);
                        return t;
                    }
                });
    }

    public Executor getExecutor() {
        return executor;
    }
}

Task.java Task.java

public abstract class Task<T extends TaskResult> implements Callable<T> {
}

TaskResult.java TaskResult.java

public abstract class TaskResult {
}

Your method awaitForResults contains a busy loop: 您的方法awaitForResults包含一个忙循环:

while(taskCompleted < submittedTasks){
    ...
    while(it.hasNext()){

This will eat CPU like crazy, and hinders the actual threads. 这将使CPU疯狂地吃光,并阻碍实际的线程。 You should either add a sleep like for instance 您应该添加一个睡眠例如

 Thread.sleep(1000);

This is Quick&Dirty but will help solving the 100% cpu. 这是Quick&Dirty,但将有助于解决100%cpu。 Alternatively but more effort is to implement some signalling mechanism so the loop waits for a signal from one of the finished tasks. 替代地,但是更多的努力是实现某种信令机制,以便循环等待来自完成的任务之一的信号。

Like others suggested, it likely doesn't make sense to have 100 threads if they're all cpu-bound, but I doubt that is really your problem. 像其他人建议的那样,如果所有线程都是cpu绑定的,那么拥有100个线程可能没有任何意义,但是我怀疑这确实是您的问题。

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

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