在本练习中,我们将尝试同步代码块。在该代码块中,我们将获得对象的锁定,以便在代码块执行时其他线程无法修改该对象。我们将创建三个线程,所有线程都将尝试操纵同一对象。每个线程将输出单个字母100次,然后将该字母加1。我们将使用的对象是StringBuffer。我们可以在String对象上进行同步,但是一旦创建字符串就无法对其进行修改,因此如果不生成新的String对象,我们将无法递增字母。最终输出应为100 A,100 B和100 C,它们都应连续显示。


创建一个类并扩展Thread类。
重写Thread的run()方法。这是同步的代码块将要去的地方。
为了使三个线程对象共享同一对象,我们将需要创建一个构造函数,该构造函数在参数中接受StringBuffer对象。
同步的代码块将从步骤3获得对StringBuffer对象的锁定。
在该块中,输出StringBuffer 100次,然后递增StringBuffer中的字母。您可以在第5章中找到有关StringBuffer(StringBuilder)的方法,以帮助解决此问题。
最后,在main()方法中,使用字母A创建单个StringBuffer对象,然后创建类的三个实例并启动所有三个实例。


解:

公共类OCJPThread扩展了线程{

StringBuffer sb;
public OCJPThread(StringBuffer sb) {
    this.sb =sb;
}


public void run(){
    synchronized (sb) {
        System.out.println(Thread.currentThread().getName());
        for(int i=1;i<=100;i++)
            System.out.print(sb);

        System.out.println();
        sb.setCharAt(0, (char)(sb.charAt(0)+1));


    }
}

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

    t1.start();
    t2.start();
    t3.start();
}


}
输出
线程-0
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
线程2
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
线程1
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC

问题:如果我使用Stringbuilder或StringBuffer,则无所谓,因为我使用的是同步块。

但是,如果我使用synced(this)而不是stringbuffer对象。输出不可预测。由于字符串缓冲区已经同步,为什么我们需要自己做呢?

最佳答案

StringBuffer是同步的,但仅在每个单独的方法调用上同步。这意味着当您不使用同步时,打印字符串缓冲区值的部分不会在同步块内完成。在此期间,其他线程之一可以更新缓冲区。发生这种情况时,打印件将显示新值。您真的不知道哪个线程会首先更新缓冲区。

同样,线程可以在对sb.charAt()的调用和对sb.setCharAt()的调用之间更改值。因此,增量本身的结果可能是不可预测的。

注意:在this上进行同步意味着每个线程都在不同的锁上进行同步,因此就好像根本不同步一样。

08-04 02:59
查看更多