synchronized同步方法的问题

有些情况下,在方法上面加synchronized同步,会有性能问题。
请看下面代码,来计算下两个线程执行的耗时:

package com.sutaoyu.Thread;

public class SynchronizedTest02 {
public static long begin1;
public static long end1;
public static long begin2;
public static long end2; public static void main(String[] args) {
final LongTask longTask = new LongTask(); Thread t1 = new Thread() {
public void run() {
begin1 = System.currentTimeMillis();
//执行耗时较长的任务方法
longTask.changeNum(true);
end1 = System.currentTimeMillis();
}
}; Thread t2 = new Thread() {
public void run() {
begin2 = System.currentTimeMillis();
//执行耗时较长的任务方法
longTask.changeNum(false);
end2 = System.currentTimeMillis();
}
}; t1.start();
t2.start(); //先让主线程睡眠,保证t1和t2线程执行完毕之后再计算时间
try {
Thread.sleep(10000);
}catch(InterruptedException e) {
e.printStackTrace();
} long begin = 0;
long end = 0; //将先执行的线程的时间和最后执行线程的时间获取到
if(begin1 > begin2) {
begin = begin2;
}else {
begin = begin1;
} if(end1 > end2) {
end = end1;
}else {
begin = begin1;
} if(end1 > end2) {
end = end1;
}else {
end = end2;
} System.out.println("两个线程总共耗时:" + (end -begin)/1000 + "秒"); }
}

使用同步代码块完善上面代码

上面代码打印结果是6秒,里面使用Thread.sleep方法来模拟了一个执行耗时较长的代码,假设这段代码并不会涉及到安全问题,所以就没有比较加入同步了。
来使用synchronized代码块来修改下上面的LongTask类。

package com.sutaoyu.Thread;

public class SynchronizedTest02 {
public static long begin1;
public static long end1;
public static long begin2;
public static long end2; public static void main(String[] args) {
final LongTask longTask = new LongTask(); Thread t1 = new Thread() {
public void run() {
begin1 = System.currentTimeMillis();
//执行耗时较长的任务方法
longTask.changeNum(true);
end1 = System.currentTimeMillis();
}
}; Thread t2 = new Thread() {
public void run() {
begin2 = System.currentTimeMillis();
//执行耗时较长的任务方法
longTask.changeNum(false);
end2 = System.currentTimeMillis();
}
}; t1.start();
t2.start(); //先让主线程睡眠,保证t1和t2线程执行完毕之后再计算时间
try {
Thread.sleep(10000);
}catch(InterruptedException e) {
e.printStackTrace();
} long begin = 0;
long end = 0; //将先执行的线程的时间和最后执行线程的时间获取到
if(begin1 > begin2) {
begin = begin2;
}else {
begin = begin1;
} if(end1 > end2) {
end = end1;
}else {
begin = begin1;
} if(end1 > end2) {
end = end1;
}else {
end = end2;
} System.out.println("两个线程总共耗时:" + (end -begin)/1000 + "秒"); }
}

修改后将需要同步的代码放到synchronized代码块中,再次运行SynchronizedTest02类,打印结果是3秒,因为那段耗时较长的代码是在异步情况下运行,所以节省了一些时间。

注意:多个线程在执行synchronized同步代码块时,代码块括号里面可以传入任意对象,但一定要保证多个线程访问的是同一个对象。

比如将LongTask中的成员变量Object obj = new Object();移动到changeNum方法中,在t1和t2两个线程中分别调用了changeNum方法,这样会各自创建一个Object对象,仍然会导致线程安全问题发生。

最新文章

  1. 学习 ---- JavaScript 高级设计程序 第三章(数据类型)
  2. loadrunner用javavuser进行接口测试
  3. UC如被百度控股,手机qq浏览器改如何进攻和防守
  4. Playmaker Input篇教程之引入的核心概念
  5. linux面试题及答案
  6. BZOJ 1013 球形空间产生器
  7. ASP.net+SQL server2008简单的数据库增删改查 VS2012
  8. 使用tcpdump抓Android网络包
  9. 记一次python的一些参数
  10. [bzoj4883][Lydsy2017年5月月赛]棋盘上的守卫
  11. web.xml中Servlet3.1版本的头信息格式
  12. regression | p-value | Simple (bivariate) linear model | 线性回归 | 多重检验 | FDR | BH | R代码
  13. shibie
  14. 用distinct or array_unique
  15. js中字符替换函数String.replace()使用技巧
  16. 蒙特·卡罗方法(Monte Carlo method)
  17. Linux regulator framework(1) - 概述【转】
  18. BitMap的简单实现
  19. linux服务器安全配置10大技巧
  20. TDDL实践

热门文章

  1. ecplise maven springmvc工程搭建
  2. QObject 源代码阅读
  3. java传统的文件拷贝 相当于两个大缸需要通过一个勺子(字节数组)一点一点运过去
  4. JAVA Junit4
  5. Linux禁止root账户远程登录
  6. jenkins+maven+Tomcat8实现热部署
  7. 使用URLConnection发送http请求实现简单爬虫(可以配置代理)
  8. 安装GourdScanV2的踩坑过程
  9. 利用poi来向execl中写入对象
  10. python之旅:迭代器、生成器、面向过程编程