2013-08-03 58 views
12

这次演习是直出凯西Seirra和贝尔·贝茨synchronized块不工作

SCJP同步码

块在这个练习中,我们将尝试的代码块同步的。在该代码块中,我们将获取对象的锁定,以便其他线程在代码块执行时无法对其进行修改。我们将创建三个线程,这些线程将尝试操纵同一个对象。每个线程将输出一个字母100次,然后将该字母加1。我们将使用的对象是StringBuffer。

我们可以对一个String对象进行同步,但是一旦创建它们就不能修改它们的字符串 ,所以我们无法在不生成新的String对象的情况下递增字母。最终产出应该有100个As,100 Bs和100 Cs全部在连续的行中。

  1. 创建一个类并扩展Thread类。
  2. 重写Thread的run()方法。这是同步的 代码块将去的地方。
  3. 对于我们的三个线程对象共享相同的对象,我们需要创建一个构造函数,它接受参数中的一个StringBuffer对象。
  4. 的代码将获得锁的StringBuffer 对象上从步骤3
  5. 内块,输出StringBuffer的100次,然后递增 在StringBuffer的信同步块。你可以检查第6章的StringBuffer 方法,这将有助于此。
  6. 最后,在main()方法中,使用字母A创建一个使用 字母A的StringBuffer对象,然后创建我们类的三个实例并启动它们的全部三个。

我写了下面的类以上的运动(而不是100,我打印10个字符)

class MySyncBlockTest extends Thread { 

    StringBuffer sb; 

    MySyncBlockTest(StringBuffer sb) { 
     this.sb=sb; 
    } 

    public static void main (String args[]) { 
     StringBuffer sb = new StringBuffer("A"); 
     MySyncBlockTest t1 = new MySyncBlockTest(sb); 
     MySyncBlockTest t2 = new MySyncBlockTest(sb); 
     MySyncBlockTest t3 = new MySyncBlockTest(sb); 
     t1.start(); 
     t2.start(); 
     t3.start(); 
    } 

    public void run() { 
     synchronized(this) { 
      for (int i=0; i<10; i++) { 
       System.out.print(sb); 
      } 
      System.out.println(""); 
      if (sb.charAt(0)=='A') 
       sb.setCharAt(0, 'B'); 
      else 
       sb.setCharAt(0, 'C'); 
     } 
    } 
} 

我期待的输出类似于下面的(10,10个烧烤和10铯),但没有得到它。

AAAAAAAAAA 
BBBBBBBBBB 
CCCCCCCCCC 

像下面的三个线程相反,我得到了不同的输出 得到一个机会,进入循环其他完成之前。

AAAAAAAAAAAAAAAAAA 
ABB 
ACCCCCCCC 

我的问题是为什么run方法中的synchronized块不工作?

+0

请问,谁降级,发布说明,为什么 –

+0

为什么我会得到-1?它是一个真正的问题! – atsurti

+0

请不要在使用StringBuilder时使用StringBuffer。 StringBuffer已经成为近10年来的传统课程。 –

回答

19

4的代码synchronized块将从步骤3

那么得到的StringBuffer对象上的锁,你不这样做,是吗?

synchronized(this) { 

你获得在其上该run()方法被调用的MySyncBlockTest实例的锁。那......不会做任何事情。这种资源没有争议;每个Thread都有其自己的实例MySyncBlockTest

+1

知道了!我已将其更改为同步(sb)及其工作! – atsurti

+0

不知道为什么这个工作,但有一个全局类变量没有 私人最终对象锁=新的对象(); 同步(锁定){... ''' – Alex

4

您应该锁定StringBuffer对象上

synchronized(sb) { 
      for (int i=0; i<10; i++) { 
       System.out.print(sb); 
      } 
0

你想要的输出,这就是可能的单个对象的多个线程,试试这个方法

public class MultiThreading implements Runnable { 
public static void main(String [] arg) 
{ 
MultiThreading a=new MultiThreading(20); 
Thread t0=new Thread(a); // 
Thread t1=new Thread(a); // Multiple Threads of single object 
Thread t2=new Thread(a); // 
t0.start(); 
t1.start(); 
t2.start(); 
} 
private int count; 
MultiThreading(int a) 
{this.count=a; 
} 
public void run() 
{ 
synchronized(this){ 
String t_name=new String(""); 
t_name=Thread.currentThread().getName().toString(); 
    for(int i=0;i<count;i++) 
    if(t_name.equals("Thread-0".toString())) // mean t0 
     System.out.print("A"); 

    else if(t_name.equals("Thread-1".toString())) // mean t1 
     System.out.print("B"); 

    else if(t_name.equals("Thread-2".toString())) // mean t1 
     System.out.print("C"); 
System.out.print("\n"); 
        } 
} // end of run 
} 
0
EXERCISE 9-2 from SCJP: 
Try this For Synchronozing on stringBuffer Object. 
It is giving required output. 




class letterThread extends Thread 
{ 
StringBuffer putLetter; 

letterThread(StringBuffer str) 
{ 
    this.putLetter=str; 
} 

public void run() 
{ 

    synchronized (putLetter) { 

     if(Thread.currentThread().getName().equals("th2")) 
     { 
      this.putLetter=new StringBuffer("B"); 
     } 
     else if(Thread.currentThread().getName().equals("th3")) 
     { 
      this.putLetter=new StringBuffer("C"); 
     } 

     for(int i=1;i<11;i++) 
     { 
      System.out.print(putLetter+""); 
     } 
     System.out.println(); 
    } 
} 
} 

public class Manager 
{ 
public static void main(String args[]) 
{ 
    StringBuffer str=new StringBuffer("A"); 
    letterThread th1=new letterThread(str); 
    letterThread th2=new letterThread(str); 
    letterThread th3=new letterThread(str); 

    th1.setName("th1"); 
    th2.setName("th2"); 
    th3.setName("th3"); 

    th1.start(); 
    th2.start(); 
    th3.start(); 

} 
} 
-2

您可以取代

 if (sb.charAt(0)=='A') 
      sb.setCharAt(0, 'B'); 
     else 
      sb.setCharAt(0, 'C'); 

sb.setCharAt(0, (char) (sb.charAt(0) + 1)); 
-4

package com.practice.ThreadPackage;

类ThreadParent扩展Thread {

StringBuffer data; 

public void run() { 
    synchronized (this.data) { 

     System.out.println(this.getName()); 

     for (int i = 0; i < 10; i++) { 

      System.out.print(this.data.toString()); 
     } 

     System.out.println(); 
     this.data.setCharAt(0, ((char) (this.data.charAt(0) + 1))); 
    } 
} 

ThreadParent(StringBuffer obj) { 
    this.data = obj; 
} 

}

公共类ThreadClass { 公共静态无效主要(字符串ARGS []){

StringBuffer str = new StringBuffer("A"); 
    ThreadParent obj = new ThreadParent(str); 
    ThreadParent obj1 = new ThreadParent(str); 
    ThreadParent obj2 = new ThreadParent(str); 
    obj.setName("Thread1"); 
    obj1.setName("Thread2"); 
    obj2.setName("Thread3"); 
    obj.start(); 
    obj1.start(); 
    obj2.start(); 

} 

}

+0

请解释您的答案,而不是仅仅倾销代码。为什么这是一个很好的答案?它如何解决问题? – Gray

-1

EXERCISE 13-2来自SCJP7

public class ThreadSyncronization extends Thread { 

    StringBuffer sBuffer; 
    public ThreadSyncronization(StringBuffer s,String name){ 
     this.sBuffer=s; 
     this.setName(name); 
    } 
    public ThreadSyncronization(){ 
    } 
    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     StringBuffer ch = new StringBuffer("A"); 
     Thread t1 = new ThreadSyncronization(ch,"first"); 
     Thread t2 = new ThreadSyncronization(ch,"second"); 
     Thread t3 = new ThreadSyncronization(ch,"third"); 
     t1.start(); 
     t2.start(); 
     t3.start(); 
    } 

    public void run(){ 
     synchronized (sBuffer) { 
      System.out.println(this.getName()); 
      for(int i=0;i<10;i++) { 
       System.out.print(sBuffer+":"+i+" "); 
       try{Thread.sleep(500);} catch(InterruptedException e) {System.out.println(e);} 
      }   
      System.out.println(); 
      // increment char 
      char c = this.sBuffer.charAt(0); 
      this.sBuffer.setCharAt(0, ++c); 
     } 

    } 

} 
1

我也很困惑。 Brian提供的答案是正确的

synchronized (this){ 

用于获取实例的锁定。当有一个类的单个实例和多个线程访问它时,这将非常有用。

我写了下面的程序来演示此:

package com.threads.chapter9; 

public class TestSunchronizedBlocksUsingRunnable implements Runnable { 
StringBuffer s; 

@Override 
public void run() { 
    synchronized (this) { 
     for (int i = 1; i <= 100; i++) { 
      System.out.println(i); 
     } 
     char c = s.charAt(0); 
     c++; 
     s.setCharAt(0, c); 
    } 
} 

TestSunchronizedBlocksUsingRunnable(StringBuffer s) { 
    this.s = s; 
} 

public static void main(String[] args) { 
    StringBuffer s = new StringBuffer("A"); 
    TestSunchronizedBlocksUsingRunnable instance1 = new TestSunchronizedBlocksUsingRunnable(s); 
    Thread thread1 = new Thread(instance1); 
    Thread thread2 = new Thread(instance1); 
    Thread thread3 = new Thread(instance1); 
    thread1.start(); 
    thread2.start(); 
    thread3.start(); 
} 

} 

上面的代码将显示相同的输出,但情况是完全不同的。所以你在synchronized块中使用的内容非常重要。