首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >节律任务控制器

节律任务控制器
EN

Code Review用户
提问于 2015-04-05 22:39:30
回答 2查看 111关注 0票数 2

有节奏任务控制器的目的是接受一个任务,并在客户端代码定义的循环或“节律”中执行所有排队的任务。任务返回true或false,取决于它是否“完成”。完成的任务应该从控制器的控件中移除,并且不会再次执行,而未完成的任务应该在下一个周期中执行。

我不认为我的解决方案是尽可能优化的,这是一个解决方案,需要尽可能快,因为它作为核心任务控制器在我的游戏框架!

代码语言:javascript
运行
复制
import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public final class RhythmicTaskController implements TaskController, Runnable {

    private final ExecutorService service;
    private final ConcurrentLinkedQueue<Task> queue = new ConcurrentLinkedQueue<>();

    public RhythmicTaskController(int threads, int delay, TimeUnit unit) {
        service = Executors.newFixedThreadPool(threads);

        newSingleThreadScheduledExecutor().scheduleWithFixedDelay(this, delay, delay, unit);
    }

    @Override
    public void offer(Task task) {
        queue.offer(task);
    }

    @Override
    public void run() {
        int initial = queue.size();
        ConcurrentMap<Future<Boolean>, Task> futures = new ConcurrentHashMap<>(initial);
        queue.forEach(task -> futures.put(service.submit(task::finish), task));
        futures.forEach((r, task) -> {
            try {
                if (r.get())
                    queue.remove(task);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

}
EN

回答 2

Code Review用户

回答已采纳

发布于 2015-04-06 04:46:22

这是一个解决方案,需要尽可能快,因为它作为核心任务控制器在我的游戏框架!

不一定。这都取决于一项任务平均承担了多少。除非你的任务非常快,否则,在他们的队列中鬼鬼祟祟并不重要。

代码语言:javascript
运行
复制
@Override
public void offer(Task task) {
    queue.offer(task);
}

在不检查返回值的情况下,不要使用offer。只要您使用ConcurrentLinkedQueue,就可以了,但是当您切换实现时,它就会在没有任何警告的情况下停止工作。使用类似的东西

代码语言:javascript
运行
复制
com.google.common.base.Verify(queue.offer(task));

除非删除是常见的,否则我猜您的原始实现比SpiderPig的解决方案在每次迭代中删除和重新添加任务要快。通常,迭代集合比修改集合快(两次)。但这只是猜测..。度量可以告诉您,但是度量Java性能很难。

票数 1
EN

Code Review用户

发布于 2015-04-05 23:49:22

您可以从队列中删除所有元素,并在必要时提供它们。

代码语言:javascript
运行
复制
public void run() {
    ArrayList<Task> tasks = new ArrayList<>();
    {
      Task task;
      while((task = queue.poll()) != null) {
        tasks.add(task);
      }
    }
    for(Task task: tasks) {
      service.submit(() -> {
        if(!task.finish()) offer(task);
      });
    }
}
票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/85961

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档