synchronized同步语句块
用关键字synchronized声明方法在某些情况下是有弊端的,比如A线程调用同步方法执行一个长时间的任务,那么B线程则必须等待比较长时间。在这样的情况下可以使用synchronized同步语句块来解决。
1、synchronized方法的弊端
为了证明synchronized关键字声明方法是有弊端的,看下图示例
package mytask; import commonutils.CommonUtils; public class Task { private String getData1;
private String getData2; public synchronized void doLongTimeTask() {
try {
System.out.println("begin task");
Thread.sleep(3000);
getData1 = "长时间处理任务后从远程返回的值1 threadName="
+ Thread.currentThread().getName();
getData2 = "长时间处理任务后从远程返回的值2 threadName="
+ Thread.currentThread().getName();
System.out.println(getData1);
System.out.println(getData2);
System.out.println("end task");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package commonutils; public class CommonUtils { public static long beginTime1;
public static long endTime1; public static long beginTime2;
public static long endTime2;
}
package mythread; import commonutils.CommonUtils; import mytask.Task; public class MyThread1 extends Thread { private Task task; public MyThread1(Task task) {
super();
this.task = task;
} @Override
public void run() {
super.run();
CommonUtils.beginTime1 = System.currentTimeMillis();
task.doLongTimeTask();
CommonUtils.endTime1 = System.currentTimeMillis();
} }
package mythread; import commonutils.CommonUtils; import mytask.Task; public class MyThread2 extends Thread { private Task task; public MyThread2(Task task) {
super();
this.task = task;
} @Override
public void run() {
super.run();
CommonUtils.beginTime2 = System.currentTimeMillis();
task.doLongTimeTask();
CommonUtils.endTime2 = System.currentTimeMillis();
} }
package test; import mytask.Task;
import mythread.MyThread1;
import mythread.MyThread2; import commonutils.CommonUtils; public class Run { public static void main(String[] args) {
Task task = new Task(); MyThread1 thread1 = new MyThread1(task);
thread1.start(); MyThread2 thread2 = new MyThread2(task);
thread2.start(); try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
} long beginTime = CommonUtils.beginTime1;
if (CommonUtils.beginTime2 < CommonUtils.beginTime1) {
beginTime = CommonUtils.beginTime2;
} long endTime = CommonUtils.endTime1;
if (CommonUtils.endTime2 > CommonUtils.endTime1) {
endTime = CommonUtils.endTime2;
} System.out.println("耗时" + ((endTime - beginTime) / 1000));
}
}
结果:
begin task
长时间处理任务后从远程返回的值1 threadName=Thread-0
长时间处理任务后从远程返回的值2 threadName=Thread-0
end task
begin task
长时间处理任务后从远程返回的值1 threadName=Thread-1
长时间处理任务后从远程返回的值2 threadName=Thread-1
end task
耗时:6
2、synchronized同步代码块的使用
当两个并发线程访问同一个对象ibject中的synchronized(this)同步代码块时,一段时间内只能有一个线程被执行,另一个线程必须等待当前线程执行完这个代码块后才能执行该代码块。
package service; public class ObjectService { public void serviceMethod() {
try {
synchronized (this) {
System.out.println("begin time=" + System.currentTimeMillis());
Thread.sleep(2000);
System.out.println("end end=" + System.currentTimeMillis());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package extthread; import service.ObjectService; public class ThreadA extends Thread { private ObjectService service; public ThreadA(ObjectService service) {
super();
this.service = service;
} @Override
public void run() {
super.run();
service.serviceMethod();
} }
package extthread; import service.ObjectService; public class ThreadB extends Thread {
private ObjectService service; public ThreadB(ObjectService service) {
super();
this.service = service;
} @Override
public void run() {
super.run();
service.serviceMethod();
}
}
package test.run; import service.ObjectService;
import extthread.ThreadA;
import extthread.ThreadB; public class Run { public static void main(String[] args) {
ObjectService service = new ObjectService(); ThreadA a = new ThreadA(service);
a.setName("a");
a.start(); ThreadB b = new ThreadB(service);
b.setName("b");
b.start();
} }
结果:
begin time =1403579513572
end end 1403579515572
begin time = 1403579515572
end end =1403579517572
这里虽然使用了synchronized同步代码块,但执行的效率还是没有提高
package mytask; public class Task { private String getData1;
private String getData2; public void doLongTimeTask() {
try {
System.out.println("begin task");
Thread.sleep(3000); String privateGetData1 = "长时间处理任务后从远程返回的值 1 threadName="
+ Thread.currentThread().getName();
String privateGetData2 = "长时间处理任务后从远程返回的值2 threadName="
+ Thread.currentThread().getName(); synchronized (this) {
getData1 = privateGetData1;
getData2 = privateGetData2;
} System.out.println(getData1);
System.out.println(getData2);
System.out.println("end task");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行结果
begin task
begin task
长时间处理任务后远程返回的值1 threadName=Thread-1
长时间处理任务后远程返回的值2 threadName=Thread-0
end task
长时间处理任务后远程返回的值1 threadName=Thread-0
长时间处理任务后远程返回的值2 threadName=Thread-0
end task
耗时:3
通过上述可以看到,当一个线程访问object的一个synchronized同步代码块时,另一个线程仍然可以访问该object对象中的非synchronized(this)同步代码块。
4、一半同步,一半异步
不在synchronized块中就是异步执行,在synchronized块中就是同步执行。
package mytask; public class Task { public void doLongTimeTask() {
for (int i = 0; i < 100; i++) {
System.out.println("nosynchronized threadName="
+ Thread.currentThread().getName() + " i=" + (i + 1));
}
System.out.println("");
synchronized (this) {
for (int i = 0; i < 100; i++) {
System.out.println("synchronized threadName="
+ Thread.currentThread().getName() + " i=" + (i + 1));
}
} }
}
package mythread; import mytask.Task; public class MyThread1 extends Thread { private Task task; public MyThread1(Task task) {
super();
this.task = task;
} @Override
public void run() {
super.run();
task.doLongTimeTask();
} }
package mythread; import mytask.Task; public class MyThread2 extends Thread { private Task task; public MyThread2(Task task) {
super();
this.task = task;
} @Override
public void run() {
super.run();
task.doLongTimeTask();
} }
package test; import mytask.Task;
import mythread.MyThread1;
import mythread.MyThread2; public class Run { public static void main(String[] args) {
Task task = new Task(); MyThread1 thread1 = new MyThread1(task);
thread1.start(); MyThread2 thread2 = new MyThread2(task);
thread2.start();
}
}
如果非同步的时候会成为交叉打印,同步的话即还排队执行 。
5、synchronized代码块间的同步性
在使用synchronized(this)代码块时需要注意的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对同一个object中所有其他synchronized(this)同步代码块的访问被阻塞,这说明synchronized使用的"对象监视器"是一个。
package doubleSynBlockOneTwo; /**
* Created by Administrator on 2017/1/19 0019.
*/
public class ObjectService {
public void serviceMethodA(){
try {
synchronized (this) {
System.out.println("A begin time = " + System.currentTimeMillis());
Thread.sleep(2000);
System.out.println("A end time = " + System.currentTimeMillis());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} public void serviceMethodB(){
synchronized (this){
System.out.println("B begin time ="+System.currentTimeMillis());
System.out.println("B end time" + System.currentTimeMillis());
}
}
}
package doubleSynBlockOneTwo; import selfThread.ThreadB; /**
* Created by Administrator on 2017/1/19 0019.
*/
public class ThreadA extends Thread { private ObjectService service;
public ThreadA(ObjectService service){
super();
this.service=service;
}
public void run(){
super.run();
service.serviceMethodA();
}
}
package doubleSynBlockOneTwo; /**
* Created by Administrator on 2017/1/19 0019.
*/
public class ThreadB extends Thread { private ObjectService service;
public ThreadB(ObjectService service){
super();
this.service=service;
} public void run (){
super.run();
service.serviceMethodB();
}
}
package doubleSynBlockOneTwo; /**
* Created by Administrator on 2017/1/19 0019.
*/
public class Run {
public static void main(String [] args){
ObjectService service = new ObjectService();
ThreadA a = new ThreadA(service);
a.setName("a");
a.start();
ThreadB b = new ThreadB(service);
b.setName("b");
b.start();
}
}
A begin time = 1484798392966
A end time = 1484798394978
B begin time =1484798394978
B end time1484798394978
6、同步synchronized(this)代码块是锁定当前对象的
package synchronizedthis; /**
* Created by Administrator on 2017/1/19 0019.
*/
public class Task {
public void otherMethod(){
System.out.println("---------------------------------run--otherMethod");
} public void doLongTimeTask(){
synchronized (this){
for (int i=0;i<100;i++){
System.out.println("synchronized threadName="+Thread.currentThread().getName()+"i="+(i+1));
}
}
}
}
package synchronizedthis; /**
* Created by Administrator on 2017/1/19 0019.
*/
public class MyThread1 extends Thread {
private Task task;
public MyThread1(Task task){
super();
this.task=task;
}
public void run(){
super.run();
task.doLongTimeTask();
}
}
package synchronizedthis; /**
* Created by Administrator on 2017/1/19 0019.
*/
public class MyThread2 extends Thread { private Task task;
public MyThread2(Task task){
super();
this.task=task;
}
public void run(){
super.run();
task.doLongTimeTask();
}
}
package synchronizedthis; /**
* Created by Administrator on 2017/1/19 0019.
*/
public class Run {
public static void main(String [] args){
Task task = new Task();
MyThread1 thread1 = new MyThread1(task);
thread1.start();
MyThread2 thread2 = new MyThread2(task);
thread2.start(); }
}
synchronized threadName=Thread-0i=1
synchronized threadName=Thread-0i=2
synchronized threadName=Thread-0i=3
synchronized threadName=Thread-0i=4
synchronized threadName=Thread-0i=5
synchronized threadName=Thread-0i=6
synchronized threadName=Thread-0i=7
synchronized threadName=Thread-0i=8
synchronized threadName=Thread-0i=9
synchronized threadName=Thread-0i=10
synchronized threadName=Thread-1i=1
synchronized threadName=Thread-1i=2
synchronized threadName=Thread-1i=3
synchronized threadName=Thread-1i=4
synchronized threadName=Thread-1i=5
synchronized threadName=Thread-1i=6
synchronized threadName=Thread-1i=7
synchronized threadName=Thread-1i=8
synchronized threadName=Thread-1i=9
synchronized threadName=Thread-1i=10
synchronized同步语句块的更多相关文章
- java多线程(三)——锁机制synchronized(同步语句块)
用关键字synchronized声明方法在某些情况下是有弊端的,比如A线程调用同步方法之行一个长时间的任务,那么B线程必须等待比较长的时间,在这样的情况下可以使用synchronized同步语句快来解 ...
- java synchronized静态同步方法与非静态同步方法,同步语句块
摘自:http://topmanopensource.iteye.com/blog/1738178 进行多线程编程,同步控制是非常重要的,而同步控制就涉及到了锁. 对代码进行同步控制我们可以选择同步方 ...
- java中的synchronized同步代码块和同步方法的区别
下面这两段代码有什么区别? //下列两个方法有什么区别 public synchronized void method1(){} public void method2(){ synchronized ...
- 59、synchronized同步代码块
synchronized同步方法的问题 有些情况下,在方法上面加synchronized同步,会有性能问题.请看下面代码,来计算下两个线程执行的耗时: package com.sutaoyu.Thre ...
- 2.2synchronized同步语句块
使用synchronized虽然能够避免不同步的现象出现,但是也会出现弊端,比如代码执行时间过长,那么其他线程就必须等待该线程执行完毕释放锁之后才能拿到锁. 面对这种问题可以使用同步代码块来解决. 2 ...
- 线程同步 synchronized 同步代码块 同步方法 同步锁
一 同步代码块 1.为了解决并发操作可能造成的异常,java的多线程支持引入了同步监视器来解决这个问题,使用同步监视器的通用方法就是同步代码块.其语法如下: synchronized(obj){ // ...
- synchronized(){}同步代码块笔记(新手笔记,欢迎纠正)
/* 内容:同步代码块,目的是解决多线程中的安全问题.什么安全问题呢??就是在执行run方法时,假如线程-0刚刚获得执行权, *还没执行时,就挂那了,这时线程-1获得执行权,并进行执行,就有可能出现负 ...
- 线程执行synchronized同步代码块时再次重入该锁过程中抛异常,是否会释放锁
一个线程执行synchronized同步代码时,再次重入该锁过程中,如果抛出异常,会释放锁吗? 如果锁的计数器为1,抛出异常,会直接释放锁: 那如果锁的计数器为2,抛出异常,会直接释放锁吗? 来简单测 ...
- synchronized同步代码块锁释放
今天发现自己写的线上程序出现数据库不能同步的问题,查看日志已经停止记录,随后使用jstack查看线程的运行状况,发现有个同步线程锁住了. 以下是jstack -l 637 问题线程的内容. &quo ...
随机推荐
- day day up
复位与时钟控制器 RCC(Reset Clock Controller) 通用输入输出 GPIO(General Purpose Input/Output) 嵌套向量中断控制器 NVIC(Nested ...
- jQuery 工具大搜集
jQuery 是一个非常棒的类库,但是为了保证代码的干净以及代码的精简,它只提供最核心的功能.所以就有了很多其他的工具来丰富jQuery的功能.我在使用这些工具的时候发现我常常重复的编写一些代码,所以 ...
- Hbase Rowkey设计
转自:http://www.bcmeng.com/hbase-rowkey/ 建立Schema Hbase 模式建立或更新可以通过 Hbase shell 工具或者使用Hbase Java API 中 ...
- e554. 在浏览器状态栏中显示信息
// See also e551 精简的Applet applet.showStatus("Your Message Here"); Related Examples
- bootstrap -- css -- 表单控件
若干css样式 .form-control { display: block; width: 100%; height: 34px; padding: 6px 12px; font-size: 14p ...
- erlang的小知识,未分类。
erlang:module_loaded(module):检测模块是否已加载:
- CentOS 6.5 下Vim 配置图解
分享个CentOS 6.5 下Vim 配置图文详解,希望对大家有所帮助. 1. 登录并进入你常用的用户名下,查看其主目录 命令: # su xxx $ cd xxx $ ls -a 2.查看并建立目录 ...
- Java回调方法的设计思路
package com.test; /** * 回调方法的设计技巧,例如hibernate的getHibernateTemplate().execute(Handler h)方法 */ public ...
- java与c#的语法对比
1,命名空间与包 C#为了把实现相似功能的类组织在一起,引入了命名空间的概念(namespace) Java中与此对应的东西叫做包(package) 2,类的访问控制方面的不同 C#只有两种:publ ...
- oracle用sql 语句如何向表中插入时间?
有关日期的操作中,更多的是涉及系统当前时间,用sysdate表示即可,如果是插入其他非系统时间的日期类型数据的话,用to_date转换再插入就可以了.例: insert into 表(c_date) ...