2014-11-22 51 views
0

這是我的代碼:這個同步爲什麼不起作用?

public class TestClass { 
    public static void main(String[] args) throws Exception { 
     Thread threadOne = new Thread(new SomeRunnable("x")); 
     Thread threadTwo = new Thread(new SomeRunnable("y")); 
     threadOne.start(); 
     threadTwo.start(); 
    } 
} 

public class SomeRunnable implements Runnable { 
    private String name; 
    public SomeRunnable(String name) { 
     this.name = name; 
    } 
    @Override 
    public void run() { 
     for(int i=0;i<50;i++) { 
      NameShouter.shoutName(name); 
     } 
    } 
} 

public class NameShouter { 
    public static void shoutName(String name) { 
     synchronized (System.out) { 
      System.out.print(name); 
     } 
    } 
} 

輸出我得到的是:

xxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 

我期待的是System.out的將被同步,但事實並非如此。爲什麼?我怎樣才能讓這段代碼的工作,它會輸出:

XXXXXXXXXXX .... YYYYYYYY ....

+0

什麼是有2個含義但強迫他們跑並不平行。 – 2014-11-22 09:07:16

+0

@HamletHakobyan學習 – 2014-11-22 09:08:26

+0

你可以學習更好的方法。 :) – 2014-11-22 09:11:40

回答

2

正在同步的shoutName每一個調用,這只是意味着每名之前完全寫下一個。如果你想喊都相同的名字一個接一個,你需要移動​​周圍的循環:

public class SomeRunnable implements Runnable { 
    private String name; 
    public SomeRunnable(String name) { 
     this.name = name; 
    } 
    @Override 
    public void run() { 
     synchronized (System.out) { 
      for(int i=0;i<50;i++) { 
       NameShouter.shoutName(name); 
      } 
     } 
    } 
} 

public class NameShouter { 
    public static void shoutName(String name) { 
     System.out.print(name); 
    } 
} 

既然你提到,你可能有不同的NameShouter s表示從不同的東西(你仍然需要喊能力喊這些名字50次),可以引入喊了很多次的方法重載並傳遞PrintStream作爲參數使用:

public static void shoutName(String name, int count, PrintStream out) { 
    synchronized (out) { 
     out.print(name); 
    } 
} 

然後,你可以調用shoutName("x", 50, System.out)您當前的行爲。

隨着時間的推移,您會注意到靜態方法在這裏讓事情變得很麻煩,而且您可以使用NameShouter對象,而這些對象具有正在呼叫的資源的適當屬性以及其他任何必需的屬性。

如果您的資源不只是PrintStream,例如如果你想向圖片喊名字,也許,然後或者把任何你想喊的東西換成PrintStream(可能不是最好的想法,因爲濫用界面對於某些事情會導致難以實現),或者創建你的自己的界面,例如

public interface IResource { 
    void print(); 
} 

,敷System.out和其他任何你正在使用適當成IResource

+0

如何在循環中同步? – 2014-11-22 09:01:12

+0

但同步循環? System.out的? – 2014-11-22 09:04:28

+0

如果我不知道NameShouter使用什麼資源會怎麼樣?我將如何在這種情況下同步? – 2014-11-22 09:05:25

2

好的嘗試是這樣的:

public class TestClass { 
public static void main(String[] args) throws Exception { 
    TestClass test = new TestClass(); 
    Thread threadOne = new Thread(new SomeRunnable("x",test)); 
    Thread threadTwo = new Thread(new SomeRunnable("y",test)); 
    threadOne.start(); 
    threadTwo.start(); 
} 
} 

public class SomeRunnable implements Runnable { 
private String name; 
private TestClass test; 
public SomeRunnable(String name, TestClass test) { 
    this.name = name; 
    this.test = test; 
} 
@Override 
public void run() { 
    synchronized(test){ 
    for(int i=0;i<50;i++) { 
     NameShouter.shoutName(name); 
    } 
    } 
} 
} 

public class NameShouter { 
public static void shoutName(String name) {  
     System.out.print(name);   
} 
} 

,或者如果你不希望創建的TestClass的對象,你可以做這樣的事情:

public class Try { 
public static void main(String[] args) throws Exception { 
Try test = new Try(); 
Thread threadOne = new Thread(new SomeRunnable("x",Try.class)); 
Thread threadTwo = new Thread(new SomeRunnable("y",Try.class)); 
threadOne.start(); 
threadTwo.start(); 
} 
} 

class SomeRunnable implements Runnable { 
private String name; 
private Class test; 
public SomeRunnable(String name, Class test) { 
this.name = name; 
this.test = test; 
} 
@Override 
public void run() { 
synchronized(test){ 
for(int i=0;i<50;i++) { 
NameShouter.shoutName(name); 
} 
} 
} 
} 
+0

我該怎麼做? – 2014-11-22 09:04:09

+0

對不起兄弟愚蠢了:) – 2014-11-22 09:17:36

+0

這不是矯枉過正? – 2014-11-22 09:26:01