一个线程需要2秒,10个线程需要16-18秒。为什么?

时间:2013-10-15 06:49:19

标签: java multithreading executorservice

我的每个线程都睡了2000毫秒,我有10个这样的线程,所以我预计总睡眠时间至少为20秒,但它只会在16-18秒之间出现。对不起,如果我问的是已经被问过的话。这是我到目前为止所拥有的:

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class MyThreadPoolApp {
    public static void main(String[] args) {
        long execTime = System.currentTimeMillis();
        CountDownLatch latch = new CountDownLatch(1);
        ExecutorService executor = Executors.newFixedThreadPool(10);

        for (int i = 0; i < 10; i++) {
            executor.submit(new Task());
        }
        System.out.println("threads submitted and waiting execution");

        executor.shutdown();        
        try {
            executor.awaitTermination(1, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
        }
        execTime = System.currentTimeMillis() - execTime;
        System.out.format("%d threads finished execution \n",Task.getCount());
        System.out.println("thread time : " + Task.getTime());
        System.out.println("main time : " + execTime);

    }
}

任务在哪里:

public class Task implements Runnable {

    private static long totalTime; 
    private static int count; 
    public static long getTime(){ return totalTime; }
    public static int getCount(){ return count; }

    public void run() {
        count++;
        long startTime = System.currentTimeMillis();
        try {
            Thread.sleep(2000);
            totalTime += System.currentTimeMillis() - startTime;
        } catch (InterruptedException e) {}
    }
}

我的输出:

threads submitted and waiting execution  
10 threads finished execution   
thread time : 18001  
main time : 2020  

1 个答案:

答案 0 :(得分:1)

因为你正在搞乱各种线程对totalTime的并发更新。

试试这个:

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class MyThreadPoolApp {
    public static void main(String[] args) {
        long execTime = System.currentTimeMillis();
        CountDownLatch latch = new CountDownLatch(1);
        ExecutorService executor = Executors.newFixedThreadPool(10);

        for (int i = 0; i < 10; i++) {
            executor.submit(new Task());
        }
        System.out.println("threads submitted and waiting execution");

        executor.shutdown();
        try {
            executor.awaitTermination(1, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
        }
        execTime = System.currentTimeMillis() - execTime;
        System.out.format("%d threads finished execution \n",Task.getCount());
        System.out.println("thread time : " + Task.getTime());
        System.out.println("main time : " + execTime);
    }
}

class Task implements Runnable {

    private static long totalTime;
    private static int count;
    public static long getTime(){
        synchronized(Task.class){
            return totalTime;
        }
    }
    private static void addTime(long time){
        synchronized(Task.class){
            totalTime = totalTime + time;
        }
    }
    public static int getCount(){ return count; }

    public void run() {
        count++;
        long startTime = System.currentTimeMillis();
        try {
            Thread.sleep(2000);
            addTime(System.currentTimeMillis() - startTime);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

修改 如您所愿,在run()方法内同步:

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class MyThreadPoolApp {
    public static void main(String[] args) {
        long execTime = System.currentTimeMillis();
        CountDownLatch latch = new CountDownLatch(1);
        ExecutorService executor = Executors.newFixedThreadPool(10);

        for (int i = 0; i < 10; i++) {
            executor.submit(new Task());
        }
        System.out.println("threads submitted and waiting execution");

        executor.shutdown();
        try {
            executor.awaitTermination(1, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
        }
        execTime = System.currentTimeMillis() - execTime;
        System.out.format("%d threads finished execution \n",Task.getCount());
        System.out.println("thread time : " + Task.getTime());
        System.out.println("main time : " + execTime);
    }
}

class Task implements Runnable {

    private static long totalTime;
    private static int count;
    public static long getTime(){
        synchronized(Task.class){
            return totalTime;
        }
    }
    public static int getCount(){ return count; }

    public void run() {
        count++;
        long startTime = System.currentTimeMillis();
        try {
            Thread.sleep(2000);
            synchronized(Task.class){
                totalTime += System.currentTimeMillis() - startTime;
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}