在java中两个独立的连续任务之间共享单个线程的最佳方法是什么

时间:2015-11-09 12:04:11

标签: java multithreading

我有两个名为j1和j2的连续作业。这两个工作没有任何共享状态。 我想编写一个接收未知大小的线程池并在两个作业上共享它的程序,如果线程池大小为1,则唯一的线程用于这两个作业。在以下代码中,j2永远不会启动。 我只想要一个替代方案,以便在两个作业之间共享单个线程(例如循环法)

    @Test
    public void testConcurrency(){
        final Runnable j1 = new Runnable() {
            @Override
            public void run() {
                while (!Thread.interrupted()) {
                    System.out.println("a");
                }
            }
        };
        final Runnable j2 = new Runnable() {
            @Override
            public void run() {
                while (!Thread.interrupted()) {
                    System.out.println("b");
                }
            }
        };
        final ExecutorService executorService = Executors.newSingleThreadExecutor();
        executorService.submit(j1);
        executorService.submit(j2);
        executorService.shutdown();

    }

我正在尝试开发一个体系结构,以便在所有模块中使用特定数量的线程池来完成不同的任务。这样我就可以控制创建的线程数,我只需要将它们注入模块中。而且我不想因为像这样的代码而面临死锁。所以我想知道是否有像我提到的代码块的替代品。 我曾考虑强迫开发人员使用ScheduledExecutor而不是无限循环,我只是想知道是否有遗漏的东西我已经看不到了。

1 个答案:

答案 0 :(得分:2)

您必须自己在任务之间切换。例如,您可以通过以下方式定义抽象任务:

public abstract class AbstractContinuousTask implements Runnable {

    private long maxDurationInMs = 100;
    private ExecutorService execService;

    public AbstractContinousTask(long maxDurationInMs, ExecutorService execService) {
        this.maxDurationInMs = maxDurationInMs;
        this.execService = execService;
    }

    @Override
    public final void run() {
        long start = System.currentTimeMillis();
        while (!Thread.interrupted() && (System.currentTimeMillis() - start < maxDurationInMs)) {
            runInternal();
        }
        execService.submit(this);
    }

    public abstract void runInternal();

}

将在给定的持续时间内调用runInternal方法(您可以在返回之前设置一些调用等等)。

然后,您的任务定义变为:

    final ExecutorService executorService = Executors.newSingleThreadExecutor();
    final Runnable j1 = new AbstractContinousTask(100, executorService) {
        @Override
        public void runInternal() {
            System.out.println("a");
        }
    };
    final Runnable j2 = new AbstractContinousTask(100, executorService) {
        @Override
        public void runInternal() {
            System.out.println("b");
        }
    };

编辑: 我刚刚看到你关于开发调度架构的最后评论。您是否查看过调度库,如Quartz或Spring(使用@Scheduled注释)?

你也可以直接使用java Timer api,这样:

    Timer t = new Timer();
    t.scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
            System.out.println("a");
        }
    }, 0, 100);
    t.scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
            System.out.println("b");
        }
    }, 0, 100);