总结:
本篇主要说明synchronized(this)代码块使用,这种方式和synchronized方法都是锁定的对象实例,都是同步的,阻塞的.不同的是,synchronized(this)代码块之外的代码可以异步调用
1,syn代码块减少阻塞时间
syn方法会阻塞其他线程,通过改成syn代码块,能减少等待时间
package chapter2.synBlock; public class CommonUtils { public static long beginTime1; public static long endTime1; public static long beginTime2; public static long endTime2; } package chapter2.synBlock; public class MyThread1 extends Thread { private Task task; public MyThread1(Task ta){ super(); this.task=ta; } @Override public void run(){ super.run(); CommonUtils.beginTime1=System.currentTimeMillis(); task.longTimeTask(); CommonUtils.endTime1=System.currentTimeMillis(); } } package chapter2.synBlock; public class MyThread2 extends Thread { private Task task; public MyThread2(Task ta){ super(); this.task=ta; } @Override public void run(){ super.run(); CommonUtils.beginTime2=System.currentTimeMillis(); task.longTimeTask(); CommonUtils.endTime2=System.currentTimeMillis(); } } package chapter2.synBlock; /* * 本例对比chapter2.synBlemish包的,将syn方法改为syn代码块,运行时间缩短到3s, * 因为b线程不用等待a线程的执行的sleep过程了,只需要等待a的赋值过程, * a,b线程同时进入longTimeTask方法,sleep过程是同时进行的, * 原先的syn方法,如果有n个线程,需要执行3*n的时间,而现在只需要3s, * 需要分清是执行的过程需要同步,还是赋值过程需要同步(防止脏读), * 只需要将需要同步的代码块加上syn,其他部分执行可以并发,节约时间 * 以下是输出 begin task begin task 长时间处理任务后从远程返回的值1 Thread name=Thread-1 长时间处理任务后从远程返回的值1 Thread name=Thread-0 长时间处理任务后从远程返回的值2 Thread name=Thread-0 end task 长时间处理任务后从远程返回的值2 Thread name=Thread-0 end task 耗时:3s */ public class Run { public static void main(String[] args) { Task task=new Task(); MyThread1 mt1=new MyThread1(task); MyThread2 mt2=new MyThread2(task); mt1.start(); mt2.start(); //程序实际执行时间是这边的sleep的10s,因为如果注释掉这边的sleep, // 会导致main线程不论mt1,mt2线程是否执行完成都执行后面的耗时计算,返回0s, try { Thread.sleep(10000); } catch (InterruptedException e) { // TODO Auto-generated catch block 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)+"s"); } } package chapter2.synBlock; public class Task { private String getData1; private String getData2; public void longTimeTask(){ try{ System.out.println("begin task"); Thread.sleep(3000); String privateGetData1="长时间处理任务后从远程返回的值1 Thread name="+ Thread.currentThread().getName(); String privateGetData2="长时间处理任务后从远程返回的值2 Thread name="+ 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){ e.printStackTrace(); } } }
一半同步一半异步
package chapter2.t7; /* * 演示syn代码块同步的,不在syn块中的代码块是异步调用的,而在syn块中的是同步调用的 * 输出截取: * nonSynchronized thread name=a i=0 nonSynchronized thread name=b i=0 nonSynchronized thread name=b i=1 nonSynchronized thread name=b i=2 nonSynchronized thread name=b i=3 nonSynchronized thread name=a i=1 上面说非syn块中的执行是不同步的 进入syn代码块是排队执行的 */ public class Run { public static void main(String[] args) { Task task=new Task(); ThreadA ta=new ThreadA(task); ThreadB tb=new ThreadB(task); ta.setName("a"); tb.setName("b"); ta.start(); tb.start(); } } package chapter2.t7; public class Task { public void doLontTimeTask(){ for(int i=0;i<100;i++){ System.out.println("nonSynchronized thread name="+Thread.currentThread().getName()+ " i="+i); } System.out.println(""); synchronized (this) { for(int i=0;i<100;i++){ System.out.println("Synchronized thread name="+Thread.currentThread().getName()+ " i="+i); } } } } package chapter2.t7; public class ThreadA extends Thread { Task task; public ThreadA(Task task) { super(); this.task=task; } @Override public void run() { // TODO Auto-generated method stub super.run(); task.doLontTimeTask(); } } package chapter2.t7; public class ThreadB extends Thread { Task task; public ThreadB(Task task) { super(); this.task=task; } @Override public void run() { // TODO Auto-generated method stub super.run(); task.doLontTimeTask(); } }
参考:<java多线程编程核心技术>