在本练习中,我们将尝试同步代码块。在该代码块中,我们将获得一个对象的锁,以便其他线程在该代码块执行时无法修改它。我们将创建三个线程,它们都将尝试操作同一个对象。每个线程将输出一个字母 100 次,然后将该字母递增 1。我们将使用的对象是 StringBuffer。我们可以在 String 对象上进行同步,但字符串一旦创建就无法修改,因此如果不生成新的 String 对象,我们将无法增加字母。最终输出应该有 100 个 A、100 个 B 和 100 个 C,并且全部在不间断的行中。
创建一个类并扩展 Thread 类。
重写Thread的run()方法。这是同步代码块所在的位置。
为了让三个线程对象共享同一个对象,我们需要创建一个在参数中接受 StringBuffer 对象的构造函数。
同步代码块将从第 3 步获取 StringBuffer 对象上的锁。
在 block 内,输出 StringBuffer 100 次,然后递增 StringBuffer 中的字母。您可以查看第 5 章的 StringBuffer (StringBuilder) 方法,这将有助于解决此问题。
最后,在 main() 方法中,使用字母 A 创建一个 StringBuffer 对象,然后创建我们类的三个实例并启动所有三个实例。
解决方案:
公共(public)类 OCJPThread 扩展 Thread{
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 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 线程2 BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 线程1 CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
问题:如果我使用 Stringbuilder 或 StringBuffer,那没关系,因为我使用的是同步块(synchronized block)。
但是如果我使用synchronized(this)而不是stringbuffer对象。输出是不可预测的。既然字符串缓冲区已经同步了,为什么我们需要自己做呢?
最佳答案
您将相同的引用传递给所有三个线程。如果他们对此进行同步,那么他们都可以同时写入StringBuffer
。如果它们在公共(public) StringBuffer
上同步,则一次只有一个线程可以访问它。
关于java - 同步代码块 - 练习 13-2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44419852/