sychronized方法的弊端
如果A线程执行的sychronized方法执行一个时间比较长的任务,则B线程需要等待比较长的时间,这是可以用sychronized代码块来解决
package com.myObject;
public class Object5 {
public void mothd() {
System.out.println(Thread.currentThread().getName()+"开始模拟长时间任务");
try {
Thread.sleep(1500);
synchronized (this){
System.out.println("需要线程安全");
}
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"结束模拟长时间任务");
}
}
package com.test;
public class Sum{
public static long b1;
public static long b2;
public static long e1;
public static long e2;
}
package com.test;
import com.myObject.Object5;
public class Test5 {
public static void main(String[] args) throws InterruptedException {
final Object5 object5 = new Object5();
final long b;
final long e;
Thread threadA = new Thread() {
@Override
public void run() {
super.run();
Sum.b1=System.currentTimeMillis();
object5.mothd();
Sum.e1=System.currentTimeMillis();
}
};
Thread threadB = new Thread() {
@Override
public void run() {
super.run();
Sum.b2=System.currentTimeMillis();
object5.mothd();
Sum.e1=System.currentTimeMillis();
}
};
threadA.setName("a");
threadB.setName("b");
threadA.start();
threadB.start();
Thread.sleep(10000);
b=(Sum.b1>Sum.b2)?Sum.b2:Sum.b1;
e=(Sum.e1>Sum.e2)?Sum.e1:Sum.e2;
System.out.println((e-b)/1000);
}
}
打印结果
b开始模拟长时间任务
a开始模拟长时间任务
需要线程安全
需要线程安全
a结束模拟长时间任务
b结束模拟长时间任务
耗时3
如果将synchronized放在方法上
package com.myObject;
public class Object5 {
synchronized public void mothd() {
System.out.println(Thread.currentThread().getName() + "开始模拟长时间任务");
try {
Thread.sleep(1500);
{
System.out.println("需要线程安全");
}
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "结束模拟长时间任务");
}
}
则打印结果为
a开始模拟长时间任务
需要线程安全
a结束模拟长时间任务
b开始模拟长时间任务
需要线程安全
b结束模拟长时间任务
耗时6
将任意对象作为对象监视器
现在已经知道了synchronized同步方法和synchronized(this)同步代码块,现在来研究synchronized(非this对象)同步代码块
1)在多个线程持有“对象监视器”为同一个对象时,同一时间只有一个线程可以执行synchronized(非this对象)同步代码块中的代码
package com.myObject;
public class Object1 {
private String username;
private String password;
private String str = new String();
public void setUsernamePassword(String username, String password) {
try {
synchronized(str){
System.out.println(System.currentTimeMillis()+" "+Thread.currentThread().getName()+":begin");
this.username=username;
Thread.sleep(3000);
this.password=password;
System.out.println(System.currentTimeMillis()+" "+Thread.currentThread().getName()+":end");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package com.myThread;
import com.myObject.Object1;
public class Thread1a extends Thread {
Object1 object1;
public Thread1a(Object1 object1) {
this.object1 = object1;
}
@Override
public void run() {
super.run();
object1.setUsernamePassword("a", "aa");
}
}
package com.myThread;
import com.myObject.Object1;
public class Thread1b extends Thread {
Object1 object1;
public Thread1b(Object1 object1) {
this.object1 = object1;
}
@Override
public void run() {
super.run();
object1.setUsernamePassword("b", "bb");
}
}
package com.test;
import com.myObject.Object1;
import com.myThread.Thread1a;
import com.myThread.Thread1b;
public class Test1 {
public static void main(String[] args) throws InterruptedException {
// 测试1
Object1 object1 = new Object1();
Thread1a thread1a = new Thread1a(object1);
thread1a.setName("a");
thread1a.start();
Thread1b thread1b = new Thread1b(object1);
thread1b.setName("b");
thread1b.start();
}
}
打印结果
1452738622275 a:begin
1452738625275 a:end
1452738625275 b:begin
1452738628275 b:end
2)使用synchronized(非this对象)同步代码块,若线程执行的方法或者代码块所持有的监视对象不同,则执行是异步的
package com.myObject;
public class Object2 {
private String username;
private String password;
private String str = new String();
public void setUsernamePassword(String username, String password) {
try {
synchronized(str){
System.out.println(System.currentTimeMillis()+" "+Thread.currentThread().getName()+":begin");
this.username=username;
Thread.sleep(3000);
this.password=password;
System.out.println(System.currentTimeMillis()+" "+Thread.currentThread().getName()+":end");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized public void setUsernamePassword2(String username, String password) {
try {
System.out.println(System.currentTimeMillis()+" "+Thread.currentThread().getName()+":begin");
this.username=username;
Thread.sleep(3000);
this.password=password;
System.out.println(System.currentTimeMillis()+" "+Thread.currentThread().getName()+":end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package com.myThread;
import com.myObject.Object2;
public class Thread2b extends Thread {
Object2 object2;
public Thread2b(Object2 object2) {
this.object2 = object2;
}
@Override
public void run() {
super.run();
object2.setUsernamePassword2("b", "bb");
}
}
package com.myThread;
import com.myObject.Object2;
public class Thread2a extends Thread {
Object2 object2;
public Thread2a(Object2 object2) {
this.object2 = object2;
}
@Override
public void run() {
super.run();
object2.setUsernamePassword("a", "aa");
}
}
package com.test;
import com.myObject.Object2;
import com.myThread.Thread2a;
import com.myThread.Thread2b;
public class Test2 {
public static void main(String[] args) throws InterruptedException {
// 测试2
Object2 object2 = new Object2();
Thread2a thread2a = new Thread2a(object2);
thread2a.setName("a");
thread2a.start();
Thread2b thread2b = new Thread2b(object2);
thread2b.setName("b");
thread2b.start();
}
}
打印结果
1452740150310 a:begin
1452740150310 b:begin
1452740153310 a:end
1452740153311 b:end
synchronized(x)结论
1)多个线程同时执行synchronized(x)同步代码块,线程呈同步
2)当某线程持有x对象,而其他线程执行x对象中的synchronized同步方法或者synchronized(this)同步代码块,线程呈同步
针对第二点,有以下实例
package com.myObject;
public class Object3a {
public void setObject(Object3a object3a, Object3b object3b) {
try {
synchronized (object3b) {
System.out.println(System.currentTimeMillis() + " "+ Thread.currentThread().getName() + ":begin");
Thread.sleep(3000);
System.out.println(System.currentTimeMillis() + " "+ Thread.currentThread().getName() + ":end");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package com.myObject;
public class Object3b {
synchronized public void print() {
try {
System.out.println(System.currentTimeMillis() + " "+ Thread.currentThread().getName() + ":begin");
Thread.sleep(3000);
System.out.println(System.currentTimeMillis() + " "+ Thread.currentThread().getName() + ":end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void print2() {
try {
synchronized(this){
System.out.println(System.currentTimeMillis() + " "+ Thread.currentThread().getName() + ":begin");
Thread.sleep(3000);
System.out.println(System.currentTimeMillis() + " "+ Thread.currentThread().getName() + ":end");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package com.myThread;
import com.myObject.Object3a;
import com.myObject.Object3b;
public class Thread3a extends Thread {
Object3a object3a;
Object3b object3b;
public Thread3a(Object3a object3a,Object3b object3b) {
this.object3a = object3a;
this.object3b = object3b;
}
@Override
public void run() {
super.run();
object3a.setObject(object3a, object3b);
}
}
package com.test;
import com.myObject.Object3a;
import com.myObject.Object3b;
import com.myThread.Thread3a;
import com.myThread.Thread3b;
public class Test3 {
public static void main(String[] args) throws InterruptedException {
Object3a object3a = new Object3a();
Object3b object3b = new Object3b();
Thread3a thread3a = new Thread3a(object3a,object3b);
thread3a.setName("a");
thread3a.start();
Thread3b thread3b = new Thread3b(object3b);
thread3b.setName("b");
thread3b.start();
}
}
package com.myThread;
import com.myObject.Object3b;
public class Thread3b extends Thread {
Object3b object3b;
public Thread3b(Object3b object3b) {
this.object3b = object3b;
}
@Override
public void run() {
super.run();
//测试1
// object3b.print();
//测试2
object3b.print2();
}
}
测试1结果打印
1452743633845 a:begin
1452743636845 a:end
1452743636845 b:begin
1452743639846 b:end
测试2结果打印
1452743674541 a:begin
1452743677542 a:end
1452743677542 b:begin
1452743680543 b:end