2013-10-15 1 views
2

내 스레드는 각각 2000 밀리 초 동안 잠을 자고 10 개의 스레드가 있기 때문에 총 절전 시간이 최소한 20 초가 될 것으로 예상했지만 16-18 초 사이에 오로지 잠자기가됩니다. 이미 물어 본 것을 묻는다면 미안해. 여기에 지금까지이 작업은 다음과 같습니다하나의 스레드는 2 초가 걸리고, 10 개의 스레드는 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 
+0

당신은 잡기있어'InterruptedException' 아니라 그것으로 아무것도. 뭔가 잘못되어서 잠을 잘 수 있다고 생각하세요? – Michael

+0

좋은 지적. 나는 그것에 대해 생각하지 않았다. 나는 그것을 밖으로 시도 할 것이다. @Michael Nope, 아무것도 없습니다 .. – Somjit

답변

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(); 
     } 
    } 
} 

편집 당신이 원하는대로, 내부 실행을 동기화() 메소드 :

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(); 
     } 
    } 
} 
+0

run() 메소드 내부에 동기화가 있다면 어떻게 될까요? 두 가지 추가 동기화 방법을 저장하지 않을까요? – Somjit

+0

예 run() 메서드 내에서 동기화 블록을 넣어 총 시간을 업데이트 할 수 있습니다! 하지만 클래스 변수를 업데이트하기 때문에 Task.class에서만 동기화됩니다. – UDPLover

관련 문제