Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java并发任务的实现_Java_Asynchronous_Concurrency_Java.util.concurrent - Fatal编程技术网

Java并发任务的实现

Java并发任务的实现,java,asynchronous,concurrency,java.util.concurrent,Java,Asynchronous,Concurrency,Java.util.concurrent,我的问题是:我最多可以运行三个并发任务。这些任务可以同时处理1到100个作业。我有许多线程不断提交单个作业,我希望尽快响应它们。在一个任务中处理100个作业所需的时间与在一个任务中处理1个作业所需的时间相同。工作的时间间隔是随机的。提交作业的线程需要阻塞,直到作业完成或超时。这里的驱动程序是快速响应提交作业的线程 因此,我当前的逻辑是:如果有

我的问题是:我最多可以运行三个并发任务。这些任务可以同时处理1到100个作业。我有许多线程不断提交单个作业,我希望尽快响应它们。在一个任务中处理100个作业所需的时间与在一个任务中处理1个作业所需的时间相同。工作的时间间隔是随机的。提交作业的线程需要阻塞,直到作业完成或超时。这里的驱动程序是快速响应提交作业的线程

因此,我当前的逻辑是:如果有<3个任务正在运行,并且有一个作业到达,则创建一个新任务来单独处理该作业。如果有3个任务正在运行,请将该作业放入队列并等待另一个任务完成,然后从队列中取出所有作业(限制为100),并创建一个任务来处理所有作业

我只是不太确定用Java设置它的最佳方法。我创建了一个简单的信号量版本,可以很好地工作,但没有利用同时提交作业的能力。我应该如何最好地扩展它以完全满足我的需求?(没有使用信号量的要求,这正是我目前所拥有的)


您可以使用带有固定大小线程池的
Executor
服务:

class ExecutorExample {
    private final static ExecutorService executorService;
    private final static long maxWaitTime = 5000;

    static {
        executorService = Executors.newFixedThreadPool(3);
    }

    private static class Response {}
    private static class Job {}

    public static Response doJob(final Job job) throws Exception {
        final Future<Response> future = executorService.submit(
            new Callable<Response>() {
                @Override
                public Response call() throws Exception {
                    return doJobInNewTask(job);
                }
            }
        );
        try {
            // get() blocks until the task finishes.
            return future.get(maxWaitTime, TimeUnit.MILLISECONDS);
        }
        catch (final TimeoutException e) {
            // we timed out, so *try* to cancel the task (may be too late)
            future.cancel(/*mayInterruptIfRunning:*/false);
            throw e;
        }
    }

    private static Response doJobInNewTask(final Job job) {
        try { Thread.sleep(maxWaitTime / 2); }
        catch (final InterruptedException ignored) {}
        return new Response();
    }

    public static void main(final String[] args) {
        final List<Thread> threads = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
            final Thread t = new Thread() {
                @Override
                public void run() {
                    try {
                        System.out.println(doJob(new Job()));
                    }
                    catch (final Exception e) {
                        System.out.println(e.getClass().getSimpleName());
                    }
                }
            };
            threads.add(t);
            t.start();
        }

        for (final Thread thread : threads) {
            try { thread.join(); }
            catch (final InterruptedException ignored) {}
        }

        System.out.println("Done!");
    }
}

这里的一个潜在问题是取消。由于日程安排已超出您的控制范围,因此任务可能会在您等待任务超时后启动,但在
cancel()
有机会完成任务之前启动。结果不会传播,但如果任务有有意义的副作用,这种方法可能会产生问题。

研究
java.util.concurrent
中的类,尤其是执行器和线程池。你可能不必重新发明轮子。@JimGarrison谢谢,我会的,我在这方面的研究到目前为止还没有给出任何明显的答案。你能给我指些更具体的吗?棘手的部分是在某些情况下一起处理排队的任务,而不是在其他情况下。默认情况下,线程池和执行器似乎没有给我那个级别的控制,但我可能看不到正确的东西。感谢@MikeStrobel,据我所知,您的代码使用ThreadPool/Future模式实现了超时要求和3个同时任务的限制。但它没有利用在一个任务中同时处理作业的能力。假设你有3个正在运行的任务,5个排队,当一个任务槽空闲时,它可以一次性完成所有5个排队的任务。啊,我错过了你说的那部分,“在一个任务中处理100个作业所需的时间与在一个任务中处理1个作业所需的时间相同。”。您可以修改我的示例,使调度的
Callable
从队列中获取尽可能多的作业,而不是捕获并运行单个任务。基本上,与调度单个作业的处理不同,您将调度一种“队列/批处理程序”(对其处理的项目数量有限制)。我尝试了您的方法,但最终发现更容易调整我以前的代码以满足要求。但是你的方法可能更好。。。如果您有任何进一步的建议,我会在stackexchange代码审查网站上发布我的新代码:
class ExecutorExample {
    private final static ExecutorService executorService;
    private final static long maxWaitTime = 5000;

    static {
        executorService = Executors.newFixedThreadPool(3);
    }

    private static class Response {}
    private static class Job {}

    public static Response doJob(final Job job) throws Exception {
        final Future<Response> future = executorService.submit(
            new Callable<Response>() {
                @Override
                public Response call() throws Exception {
                    return doJobInNewTask(job);
                }
            }
        );
        try {
            // get() blocks until the task finishes.
            return future.get(maxWaitTime, TimeUnit.MILLISECONDS);
        }
        catch (final TimeoutException e) {
            // we timed out, so *try* to cancel the task (may be too late)
            future.cancel(/*mayInterruptIfRunning:*/false);
            throw e;
        }
    }

    private static Response doJobInNewTask(final Job job) {
        try { Thread.sleep(maxWaitTime / 2); }
        catch (final InterruptedException ignored) {}
        return new Response();
    }

    public static void main(final String[] args) {
        final List<Thread> threads = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
            final Thread t = new Thread() {
                @Override
                public void run() {
                    try {
                        System.out.println(doJob(new Job()));
                    }
                    catch (final Exception e) {
                        System.out.println(e.getClass().getSimpleName());
                    }
                }
            };
            threads.add(t);
            t.start();
        }

        for (final Thread thread : threads) {
            try { thread.join(); }
            catch (final InterruptedException ignored) {}
        }

        System.out.println("Done!");
    }
}
ExecutorExample$Response@1fe4169
ExecutorExample$Response@9fdee
ExecutorExample$Response@15b123b
ExecutorExample$Response@bbfa5c
ExecutorExample$Response@10d95cd
ExecutorExample$Response@131de9b
TimeoutException
TimeoutException
TimeoutException
TimeoutException
Done!