版权声明:版权归 爱装逼的文艺小青年所有 https://blog.csdn.net/toyota_rav4/article/details/85010000
在前面的博文中,我们提到了synchronized同步方法和使用synchronized(this),通过前面的实验可以发现:多个线程调用同一个对象中不同名称的synchronized同步方法或者sychronized(this)代码块,调用的效果是按顺序执行的,也就是说是阻塞的!
本篇博文我们将写到的是关于java中可以将任意对象作为对象监视器。
当多个线程持有的“对象监视器”为同一个对象的前提下,同一时间只有一个线程可以执行synchronized(非this对象)同步代码块中的代码!
package com.demo17;
public class MyObject {
private String username;
private String password;
private String obj = new String();
public void setValue(String username , String password){
try {
synchronized (obj) {
System.out.println("进入赋值方法的线程名称:" + Thread.currentThread().getName() +
"时间:" + System.currentTimeMillis());
this.username = username;
Thread.sleep(2000);
this.password = password;
System.out.println("离开赋值方法的线程名称:" + Thread.currentThread().getName() +
" 时间:" + System.currentTimeMillis() +
" username = " + username +
" password = " + password);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package com.demo17;
public class ThreadA extends Thread {
private MyObject myObject;
public ThreadA(MyObject myObject) {
this.myObject = myObject;
}
@Override
public void run(){
myObject.setValue("a","aa");
}
}
package com.demo17;
public class ThreadB extends Thread {
private MyObject myObject;
public ThreadB(MyObject myObject) {
this.myObject = myObject;
}
@Override
public void run() {
myObject.setValue("b","bb");
}
}
package com.demo17;
public class Run {
public static void main(String[] args) {
MyObject myObject = new MyObject();
ThreadA threadA = new ThreadA(myObject);
ThreadB threadB = new ThreadB(myObject);
threadA.setName("A");
threadB.setName("B");
threadA.start();
threadB.start();
}
}
运行结果:
进入赋值方法的线程名称:A时间:1544795048292
离开赋值方法的线程名称:A 时间:1544795050293 username = a password = aa
进入赋值方法的线程名称:B时间:1544795050293
离开赋值方法的线程名称:B 时间:1544795052294 username = b password = bb
很明显是阻塞的,同步执行的!
修改MyObject如下:让多个线程持有的“对象监视器”不为同一个对象
package com.demo17;
public class MyObject {
private String username;
private String password;
//private String obj = new String();
public void setValue(String username , String password){
try {
String obj = new String();
synchronized (obj) {
System.out.println("进入赋值方法的线程名称:" + Thread.currentThread().getName() +
"时间:" + System.currentTimeMillis());
this.username = username;
Thread.sleep(2000);
this.password = password;
System.out.println("离开赋值方法的线程名称:" + Thread.currentThread().getName() +
" 时间:" + System.currentTimeMillis() +
" username = " + username +
" password = " + password);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行结果:
进入赋值方法的线程名称:A时间:1544796228604
进入赋值方法的线程名称:B时间:1544796228604
离开赋值方法的线程名称:A 时间:1544796230607 username = a password = aa
离开赋值方法的线程名称:B 时间:1544796230608 username = b password = bb
如果不是同一个对象监视器,运行的结果是异步的!
为了验证上述结论,我们再继续进行实验:
package com.demo18;
public class MyObject {
private String obj = new String ();
public void a(){
try {
synchronized (obj) {
System.out.println("a begin");
Thread.sleep(2000);
System.out.println("a end");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized public void b(){
System.out.println("b begin");
System.out.println("b end");
}
}
package com.demo18;
public class ThreadA extends Thread {
private MyObject myObject;
public ThreadA(MyObject myObject) {
this.myObject = myObject;
}
@Override
public void run() {
myObject.a();
}
}
package com.demo18;
public class ThreadB extends Thread{
private MyObject myObject;
public ThreadB(MyObject myObject) {
this.myObject = myObject;
}
@Override
public void run() {
myObject.b();
}
}
package com.demo18;
public class Run {
public static void main(String[] args) {
MyObject myObject = new MyObject();
ThreadA threadA = new ThreadA(myObject);
ThreadB threadB = new ThreadB(myObject);
threadA.start();
threadB.start();
}
}
运行结果:
a begin
b begin
b end
a end
synchronized(非this对象)代码块与 synchronized 同步方法是异步执行的效果。
修改MyOBject如下,将同步方法换成sychronized(this)同步代码块
package com.demo18;
public class MyObject {
private String obj = new String ();
public void a(){
try {
synchronized (obj) {
System.out.println("a begin");
Thread.sleep(2000);
System.out.println("a end");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void b(){
synchronized (this) {
System.out.println("b begin");
System.out.println("b end");
}
}
}
运行结果:
a begin
b begin
b end
a end
结论:synchronized(非this对象)代码块与synchronized(this)代码块是异步执行的效果。