rxJava有序(按键)任务执行

时间:2019-02-04 00:11:54

标签: java concurrency rx-java

我有一堆代表一些数据的对象。可以将这些对象写入其相应的文件。用户可能要求比以前写入文件的更改更快地进行一些更改。

说,我对文件A,文件B和文件C进行了更改,然后将其提交执行。然后,在编写它们的同时,我对文件A进行更改并将其发布。例如,有3个线程在运行。一旦第一次执行对A,B和C的更改(写入文件),对A的第一次和第二次更改将几乎同时执行。但是,我希望在第一个更改完成后应用第二个更改。

如何在rxJava中做到这一点?

另一点。我想在另一个地方执行最新更改。一种选择是等待所有任务完成。

是否有合适的RxJava原语/方法可以涵盖这两个用例?

我是RxJava的新手,但我希望这是有道理的。 Subjects在我看来是相关的,但是将会有数百个文件。

我已经有了使用自定义Executor的实现。

public class OrderingExecutor
implements Executor
{
    @Delegate
    private final Executor delegate;
    private final Map<Object, Queue<Runnable>> keyedTasks = new HashMap<>();

    public OrderingExecutor(
        Executor delegate)
    {
        this.delegate = delegate;
    }

    public void execute(
        Runnable task,
        Object key)
    {
        Objects.requireNonNull(key);

        boolean first;
        Runnable wrappedTask;
        synchronized (keyedTasks)
        {
            Queue<Runnable> dependencyQueue = keyedTasks.get(key);
            first = (dependencyQueue == null);
            if (dependencyQueue == null)
            {
                dependencyQueue = new LinkedList<>();
                keyedTasks.put(key, dependencyQueue);
            }

            wrappedTask = wrap(task, dependencyQueue, key);
            if (!first)
            {
                dependencyQueue.add(wrappedTask);
            }
        }

        // execute method can block, call it outside synchronize block
        if (first)
        {
            delegate.execute(wrappedTask);
        }

    }

    private Runnable wrap(
        Runnable task,
        Queue<Runnable> dependencyQueue,
        Object key)
    {
        return new OrderedTask(task, dependencyQueue, key);
    }

    class OrderedTask
    implements Runnable
    {

        private final Queue<Runnable> dependencyQueue;
        private final Runnable task;
        private final Object key;

        public OrderedTask(
            Runnable task,
            Queue<Runnable> dependencyQueue,
            Object key)
        {
            this.task = task;
            this.dependencyQueue = dependencyQueue;
            this.key = key;
        }

        @Override
        public void run()
        {
            try
            {
                task.run();
            }
            finally
            {
                Runnable nextTask = null;
                synchronized (keyedTasks)
                {
                    if (dependencyQueue.isEmpty())
                    {
                        keyedTasks.remove(key);
                    }
                    else
                    {
                        nextTask = dependencyQueue.poll();
                    }
                }
                if (nextTask != null)
                {
                    delegate.execute(nextTask);
                }
            }
        }
    }
}

也许可以通过某种明智的方式将其插入rxJava?

1 个答案:

答案 0 :(得分:0)

目前尚不清楚您要实现的目标,但是您可以将优先级队列放在  RxJava的顶部。

class OrderedTask implements Comparable<OrderedTask> { ... }

PriorityBlockingQueue<OrderedTask> queue = new PriorityBlockingQueue<>();

PublishSubject<Integer> trigger = PublishSubject.create();

trigger.flatMap(v -> {
   OrderedTask t = queue.poll();
   return someAPI.workWith(t);
}, 1)
.subscribe(result -> { }, error -> { });

queue.offer(new SomeOrderedTask(1));
trigger.onNext(1);

queue.offer(new SomeOrderedTask(2));
trigger.onNext(2);