程序如何保证使用执行程序框架并发执行多个线程

时间:2015-03-22 20:17:31

标签: java multithreading concurrency runnable executorservice

我正在尝试执行5个线程同时完美启动。但是考虑下面的输出,我认为它们是在同一时间开始但不是同时开始,因为年龄计数器总是以5计数结束。如果他们真正同时执行了 群体的年龄输出必须相同。真正的同时或完美同时我认为所有5个线程传递1作为年龄和所有线程打印相同的年龄而不是增量值。请纠正我。

public class ExecutorServiceTester {

public static void main(String args[]) throws InterruptedException {
    ExecutorServiceTester tester = new ExecutorServiceTester();
    tester.executeTester();
}

private void executeTester() throws InterruptedException {
    ExecutorService executorService = Executors.newFixedThreadPool(10);
    Runnable worker = new MyRunnable(1);
    for (int i = 0; i < 10; i++) {
        executorService.execute(worker);
    } executorService.shutdown();
}

public static class MyRunnable implements Runnable {
    int age = 0;

    public MyRunnable(int count) {
        this.age = count;
    }

    @Override
    public void run() {
        System.out.println(new Timestamp(new Date().getTime())+" ThreadName:"+Thread.currentThread().getName()
                + " Age " + age++);

    }
} }

输出:

2015-03-23 02:02:18.243 ThreadName:pool-1-thread-1 Age 1
2015-03-23 02:02:18.243 ThreadName:pool-1-thread-5 Age 3
2015-03-23 02:02:18.243 ThreadName:pool-1-thread-3 Age 5
2015-03-23 02:02:18.243 ThreadName:pool-1-thread-2 Age 2
2015-03-23 02:02:18.243 ThreadName:pool-1-thread-4 Age 4

尝试使用Executors.newCachedThreadPool();如果将数量增加到12,那么OUTPUT就会引起人们的兴趣

2015-03-23 02:17:57.189 **ThreadName:pool-1-thread-4 Age 1**
2015-03-23 02:17:57.189 ThreadName:pool-1-thread-10 Age 3
2015-03-23 02:17:57.189 ThreadName:pool-1-thread-12 Age 2
2015-03-23 02:17:57.189 **ThreadName:pool-1-thread-11 Age 1** ...

2 个答案:

答案 0 :(得分:1)

所有线程使用相同计数器的原因是您正在为它们提供相同的Runnable实例。只需为循环内的每个线程创建一个新的:

for (int i = 0; i < 10; i++) {
    Runnable worker = new MyRunnable(1);
    executorService.execute(worker);
}

答案 1 :(得分:0)

它可能不太理想,但如果你需要它们完全对齐,我会设置某种类型的Mark。使用System.nanoTime()将当前时间缩短到纳秒。给它一段时间等待,比如一秒钟(1_000_000_000)纳秒。确保延迟足够长(无论是什么),以便初始化所有线程并进入等待点。将MarkTime传递给创建时的每个线程。然后让每个线程都有这样的函数:

while(System.nanoTime() < MarkTime){
    // do nothing
}

Boom,当达到时间时,所有线程都关闭并运行,协调到纳秒级。

就像跑步者在比赛的起跑线上做好准备一样。他们都在不同的时间到达了这条线,但都是从同一个先发手枪射击开始的。

另外,正如@Keppil所说,你可能想为每个版本创建一个新的线程实例,而不是同一个实例的5个副本。这样你可以确定它们是独立运行的,但同时也是如此。

或者:另一种方法是在父类中设置一个布尔值,将其设置为false,在所有线程都处于活动状态后,让它们检查该布尔值。当所有加载并运行时,将boolean更改为true。效果相同,但精度可能略有下降。你有多接近它?