2017-05-11 53 views
6

,我期待它下面的代碼不起作用:的Java同步的線程工作不正常

import java.util.ArrayList; 
import java.util.List; 
import java.util.Random; 

class Worker implements Runnable { 

    public void run() { 
     System.out.println("Started."); 
     process(); 

    } 
    private Random random = new Random(); 

    private Object lock1 = new Object(); 
    private Object lock2 = new Object(); 

    private static List<Integer> list1 = new ArrayList<Integer>(); 
    private static List<Integer> list2 = new ArrayList<Integer>(); 

    public void stageOne() { 

     synchronized (lock1) { 

      try { 
       Thread.sleep(1); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      list1.add(random.nextInt(100)); 
     } 

    } 

    public void stageTwo() { 

     synchronized (lock2) { 
      try { 
       Thread.sleep(1); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      list2.add(random.nextInt(100)); 
     } 
    } 

    public void process() { 
     for(int i=0; i<1000; i++) { 
      stageOne(); 
      stageTwo(); 
     } 
    } 
    public static void show() { 
     System.out.println("List1: " + list1.size()); 
     System.out.println("List2: " + list2.size()); 
    } 
} 

public class JavaTest { 

    public static void main(String[] args) { 

     long start = System.currentTimeMillis(); 

     Thread t1 = new Thread(new Worker()); 
     t1.start(); 
     Thread t2 = new Thread(new Worker()); 
     t2.start(); 

     try { 
      t1.join(); 
      t2.join(); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     System.out.println("Completed."); 

     long end = System.currentTimeMillis(); 

     System.out.println("Time taken: " + (end - start)); 

     Worker.show(); 
    } 

} 

當我運行這個程序,我希望list1list2包含每2000個項目和程序大約需要2000毫秒。然而,很多次我得到列表少於2000個項目,雖然它完成大約2000毫秒。有時候,我甚至得到一個ArrayOutOfBounds異常

Started. 
Started. 
Exception in thread "Thread-1" java.lang.ArrayIndexOutOfBoundsException: 163 
    at java.util.ArrayList.add(ArrayList.java:459) 
    at Worker.stageOne(JavaTest.java:34) 
    at Worker.process(JavaTest.java:53) 
    at Worker.run(JavaTest.java:14) 
    at java.lang.Thread.run(Thread.java:748) 
Completed. 
Time taken: 2217 
List1: 1081 
List2: 1079 

我預計,在stageOnestageTwo每一個閉鎖裝置應相互干擾停止線程。但似乎並非如此。這段代碼有什麼問題?

回答

8

您的鎖定對象不是靜態的,因此每個線程都在不同的監視器上同步。所以這些鎖根本沒有任何效果。