Java多线程--synchronized(二)
synchronized 同步语句块
synchronized方法的缺点
直接在方法上加synchronized关键字在某些情况下存在弊端,比如线程A调用同步方法执行长时间任务,那么其他线程将会等待很长时间。
package ch02.test3;
/*
synchronized 同步代码块
*/
public class Task {
private String getData1;
private String getData2;
public synchronized void doLongTimeTask() {
try{
System.out.println("begin task");
Thread.sleep(3000);
String tmpGetData1 = "长时间执行任务返回结果1 threadname=" + Thread.currentThread().getName();
String tmpGetData2 = "长时间执行任务返回结果2 threadname=" + Thread.currentThread().getName();
getData1 = tmpGetData1;
getData2 = tmpGetData2;
System.out.println(getData1);
System.out.println(getData2);
System.out.println("end task");
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class CommonUtils {
public static long beginTime1;
public static long endTime1;
public static long beginTime2;
public static long endTime2;
}
class MyThread1 extends Thread {
private Task task;
public MyThread1(Task task) {
this.task = task;
}
@Override
public void run() {
super.run();
CommonUtils.beginTime1 = System.currentTimeMillis();
this.task.doLongTimeTask();
CommonUtils.endTime1 = System.currentTimeMillis();
}
}
class MyThread2 extends Thread {
private Task task;
public MyThread2(Task task) {
this.task = task;
}
@Override
public void run() {
super.run();
CommonUtils.beginTime2 = System.currentTimeMillis();
this.task.doLongTimeTask();
CommonUtils.endTime2 = System.currentTimeMillis();
}
}
class Run {
public static void main(String[] args) {
Task task = new Task();
MyThread1 myThread1 = new MyThread1(task);
myThread1.start();
MyThread2 myThread2 = new MyThread2(task);
myThread2.start();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
long beginTime = Math.min(CommonUtils.beginTime1, CommonUtils.beginTime2);
long endTime = Math.max(CommonUtils.endTime1, CommonUtils.endTime2);
System.out.println("总耗时:"+ (endTime - beginTime) / 1000 + "s");
}
}
output:
begin task
长时间执行任务返回结果1 threadname=Thread-0
长时间执行任务返回结果2 threadname=Thread-0
end task
begin task
长时间执行任务返回结果1 threadname=Thread-1
长时间执行任务返回结果2 threadname=Thread-1
end task
总耗时:6s
synchronized同步代码块的使用
修改doLongTimeTask()方法,去掉方法上的synchronized,在其中添加同步代码块:
public void doLongTimeTask() {
try{
System.out.println("begin task");
Thread.sleep(3000);
String tmpGetData1 = "长时间执行任务返回结果1 threadname=" + Thread.currentThread().getName();
String tmpGetData2 = "长时间执行任务返回结果2 threadname=" + Thread.currentThread().getName();
synchronized (this) {
getData1 = tmpGetData1;
getData2 = tmpGetData2;
}
System.out.println(getData1);
System.out.println(getData2);
System.out.println("end task");
}catch (InterruptedException e) {
e.printStackTrace();
}
}
output:
begin task
begin task
长时间执行任务返回结果1 threadname=Thread-1
长时间执行任务返回结果2 threadname=Thread-0
end task
长时间执行任务返回结果1 threadname=Thread-0
长时间执行任务返回结果2 threadname=Thread-0
end task
总耗时:3s
当一个线程访问同步代码块时,其他线程仍然可以访问该对象的非同步代码块
方法中线程在synchronized (this) 同步代码块是同步的,不在同步代码块的部分是异步的
- 和synchronized方法相似,当一个线程访问anyObject对象的synchronized(this)同步代码块时,其他线程中所有同步代码块的访问将被阻塞,说明synchronized使用的“对象监视器”是一个。
小结
- synchronized同步方法
1.1 同一时间只能有一个线程执行synchronized同步方法。
1.2 对同一对象的所有其他synchronized同步方法和synchronized(this)同步代码块调用呈阻塞状态。 - synchronized(this)同步代码块同步代码块
1.1 同一时间只能有一个线程执行synchronized(this)同步代码块。
1.2 对同一对象的所有其他synchronized同步方法和synchronized(this)同步代码块调用呈阻塞状态。
作者:lykxbg —— 来一块小饼干
出处:http://www.cnblogs.com/lykxbg/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。