Queue中的Java线程一旦完成任务,就需要休眠

时间:2015-01-19 13:42:42

标签: java multithreading queue

我有以下案例来建模

程序首先查询每个接收参数的数据库并了解要运行的任务量。

定义了具有一些固定最大线程的线程队列来执行任务。每个任务都会启动一个流程,该流程可以具有不同的配任务完成后,每个任务都有一个可配置的休眠时间。

一旦任务休眠,它就无法阻止执行队列中的某个点。执行队列必须继续执行准备执行的任务

我发现由于某种原因很难编码(主要是由于最后的要求) 任何帮助将不胜感激

由于

1 个答案:

答案 0 :(得分:1)

这是一个冗长的,但是用于说明预定的重新提交者的直接代码,我还没有测试过:)

import java.util.Deque;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.concurrent.*;

interface Repeatable {
    boolean shouldBeRepeated();
    /**
     * @return how long to sleep
     */
    long delayBeforeRepeat();

    /**
     * @return "initial" state of this task instance, so this state can be resubmitted for repeated execution
     */
    BusinessTask reset();
}

/**
 * Whatever suits your business logic
 */
interface BusinessTask extends Callable<Repeatable> {
}

class BusinessTaskCompletionData {
    final BusinessTask businessTask;

    /**
     * Timestamp when this task should be resubmitted
     */
    final long nextSubmitTime;

    BusinessTaskCompletionData(BusinessTask businessTask, long nextSubmitTime) {
        this.businessTask = businessTask;
        this.nextSubmitTime = nextSubmitTime;
    }
}

class TaskResusltsConsumer implements Runnable {

    private final CompletionService<Repeatable> completionService;
    private final Deque<BusinessTaskCompletionData> completedTasks;

    TaskResusltsConsumer(ExecutorService executor, Deque<BusinessTaskCompletionData> completedTasks) {
        this.completedTasks = completedTasks;
        completionService = new ExecutorCompletionService<>(executor);
    }

    @Override
    public void run() {
        while (true) {
            try {
                Future<Repeatable> completedBusinessTask = completionService.take();
                Repeatable repeatable = completedBusinessTask.get();
                if (repeatable.shouldBeRepeated()) {
                    completedTasks.add(new BusinessTaskCompletionData(repeatable.reset(),
                            System.currentTimeMillis() + repeatable.delayBeforeRepeat()));
                }
            } catch (ExecutionException | InterruptedException ie) {
                // handle somehow
            }
        }
    }
}

class TasksSupplier implements Runnable {

    private final Deque<BusinessTaskCompletionData> completedTasks;
    private final ExecutorService executor;

    TasksSupplier(Deque<BusinessTaskCompletionData> completedTasks, ExecutorService executor) {
        this.completedTasks = completedTasks;
        this.executor = executor;
    }

    @Override
    public void run() {
        while (true) {
            BusinessTask t = getTaskSomehow();
            executor.submit(getTaskSomehow());
        }
    }

    private BusinessTask getTaskSomehow() {
        // implement
        return null;
    }
}

/**
 * Actual implementation of logic to obtain 'initial state' of task to repeat and repeat schedule
 */
class BusinessData implements Repeatable {
    // whatever
}

public class SOTest {

    public static void main(String[] args) {

        final LinkedList<BusinessTaskCompletionData> tasksToRepeat = new LinkedList<>();

        // workers pool
        final ExecutorService workersPool = Executors.newFixedThreadPool(10);

        // controllers pool: 1 thread for supplier, the other for results consumer
        final ExecutorService controllersPool = Executors.newFixedThreadPool(2);
        controllersPool.submit(new TasksSupplier(tasksToRepeat, workersPool));
        controllersPool.submit(new TaskResusltsConsumer(workersPool, tasksToRepeat));

        // resubmitter scheduled pool
        ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor();
        scheduledExecutor.scheduleWithFixedDelay(new Runnable() {
                @Override
                public void run() {
                    long now = System.currentTimeMillis();
                    Iterator<BusinessTaskCompletionData> it = tasksToRepeat.iterator();
                    while (it.hasNext()) {
                        BusinessTaskCompletionData data = it.next();
                        if (data.nextSubmitTime >= now) {
                            workersPool.submit(data.businessTask);
                            it.remove();
                        }
                    }
                }
            },
            // initial delay of 1 sec
            1000,
            // periodic delay of 1 sec
            1000,
            TimeUnit.MILLISECONDS
        );
    }

}