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

Java 一个线程需要2秒,10个线程需要16-18秒。为什么?,java,multithreading,executorservice,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.TimeUni

我的每个线程睡眠时间为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);

    }
}
我的输出:

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

因为您正在处理各种线程对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();
        }
    }
}
import java.util.concurrent.CountDownLatch;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
导入java.util.concurrent.TimeUnit;
公共类MyThreadPoolApp{
公共静态void main(字符串[]args){
long execTime=System.currentTimeMillis();
CountDownLatch闩锁=新的CountDownLatch(1);
ExecutorService executor=Executors.newFixedThreadPool(10);
对于(int i=0;i<10;i++){
执行者。提交(新任务());
}
System.out.println(“提交并等待执行的线程”);
executor.shutdown();
试一试{
执行人。等待终止(1,时间单位。分钟);
}捕捉(中断异常e){
}
execTime=System.currentTimeMillis()-execTime;
System.out.format(“%d个线程已完成执行\n”,Task.getCount());
System.out.println(“线程时间:+Task.getTime());
System.out.println(“主时间:+execTime”);
}
}
类任务实现可运行{
私有静态长时间;
私有静态整数计数;
公共静态长getTime(){
已同步(Task.class){
返回总时间;
}
}
专用静态无效添加时间(长时间){
已同步(Task.class){
总时间=总时间+时间;
}
}
公共静态int getCount(){return count;}
公开募捐{
计数++;
long startTime=System.currentTimeMillis();
试一试{
《睡眠》(2000年);
addTime(System.currentTimeMillis()-startTime);
}捕捉(中断异常e){
e、 printStackTrace();
}
}
}
编辑 如您所愿,在run()方法中同步:

import java.util.concurrent.CountDownLatch;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
导入java.util.concurrent.TimeUnit;
公共类MyThreadPoolApp{
公共静态void main(字符串[]args){
long execTime=System.currentTimeMillis();
CountDownLatch闩锁=新的CountDownLatch(1);
ExecutorService executor=Executors.newFixedThreadPool(10);
对于(int i=0;i<10;i++){
执行者。提交(新任务());
}
System.out.println(“提交并等待执行的线程”);
executor.shutdown();
试一试{
执行人。等待终止(1,时间单位。分钟);
}捕捉(中断异常e){
}
execTime=System.currentTimeMillis()-execTime;
System.out.format(“%d个线程已完成执行\n”,Task.getCount());
System.out.println(“线程时间:+Task.getTime());
System.out.println(“主时间:+execTime”);
}
}
类任务实现可运行{
私有静态长时间;
私有静态整数计数;
公共静态长getTime(){
已同步(Task.class){
返回总时间;
}
}
公共静态int getCount(){return count;}
公开募捐{
计数++;
long startTime=System.currentTimeMillis();
试一试{
《睡眠》(2000年);
已同步(Task.class){
totalTime+=System.currentTimeMillis()-startTime;
}
}捕捉(中断异常e){
e、 printStackTrace();
}
}
}

您正在捕获
InterruptedException
而没有对其执行任何操作。你认为那里可能出了什么问题,导致睡眠中断吗?说得对。我没想过。我试试看@Michael不,那里什么都没有..如果将synchronized放在run()方法中呢?将保存另外两个同步方法,不是吗?是的,您可以将同步块放入run()方法中以更新总时间!但仅在Task.class上同步,因为您正在更新类变量。
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();
        }
    }
}
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();
        }
    }
}