这一章节我们来讨论一下缓解同步方法的隐患-同步代码块。
1.思路:把同步方法,降低同步的粒度,同步到代码块
2.根据上一章节的例子,我们把代码修改一下
(1)第一种方法,把同步标记移到更新的那一栏里面去,一般来说大部分都是更新的时候需要同步数据
package com.ray.deepintothread.ch02.topic_9; /** * 从头认识多线程-2.8 缓解同步方法的隐患-同步代码块<br> * * @author RayLee * */ public class ReliefThreatOfSynch { public static void main(String[] args) throws InterruptedException { MyService myService = new MyService(); ThreadOne threadOne = new ThreadOne(myService); Thread thread = new Thread(threadOne); thread.start(); ThreadTwo threadTwo = new ThreadTwo(myService); Thread thread2 = new Thread(threadTwo); thread2.start(); Thread.sleep(10000); System.out.println("application use time:" + (MyTimeUtil.END_TIME - MyTimeUtil.START_TIME)); } } class ThreadOne implements Runnable { private MyService myService; public ThreadOne(MyService myService) { this.myService = myService; } @Override public void run() { myService.service(); } } class ThreadTwo implements Runnable { private MyService myService; public ThreadTwo(MyService myService) { this.myService = myService; } @Override public void run() { myService.service(); } } class MyService { private void queryDataFromServer() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } /** * 增加同步机制 */ private synchronized void updateDataFromServer() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } private void retrunDataFromServer() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } public void service() { long startTime = System.currentTimeMillis(); if (MyTimeUtil.START_TIME == 0) { MyTimeUtil.START_TIME = startTime; } queryDataFromServer(); updateDataFromServer(); retrunDataFromServer(); long endTime = System.currentTimeMillis(); if (endTime > MyTimeUtil.END_TIME) { MyTimeUtil.END_TIME = endTime; } System.out.println("Thread name:" + Thread.currentThread().getName() + " user time:" + (endTime - startTime)); } } class MyTimeUtil { public static long START_TIME = 0; public static long END_TIME = 0; }
输出:
Thread name:Thread-0 user time:3000
Thread name:Thread-1 user time:4000
application use time:4000
(2)第二种方法,直接调用方法的时候加上同步标志
package com.ray.deepintothread.ch02.topic_9; /** * 从头认识多线程-2.8 缓解同步方法的隐患-同步代码块<br> * * @author RayLee * */ public class ReliefThreatOfSynch2 { public static void main(String[] args) throws InterruptedException { MyService2 myService = new MyService2(); ThreadThree threadThree = new ThreadThree(myService); Thread thread = new Thread(threadThree); thread.start(); ThreadFour threadFour = new ThreadFour(myService); Thread thread2 = new Thread(threadFour); thread2.start(); Thread.sleep(10000); System.out.println("application use time:" + (MyTimeUtil2.END_TIME - MyTimeUtil2.START_TIME)); } } class ThreadThree implements Runnable { private MyService2 myService; public ThreadThree(MyService2 myService) { this.myService = myService; } @Override public void run() { myService.service(); } } class ThreadFour implements Runnable { private MyService2 myService; public ThreadFour(MyService2 myService) { this.myService = myService; } @Override public void run() { myService.service(); } } class MyService2 { private void queryDataFromServer() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } private void updateDataFromServer() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } private void retrunDataFromServer() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } public void service() { long startTime = System.currentTimeMillis(); if (MyTimeUtil2.START_TIME == 0) { MyTimeUtil2.START_TIME = startTime; } queryDataFromServer(); synchronized (this) { updateDataFromServer(); } retrunDataFromServer(); long endTime = System.currentTimeMillis(); if (endTime > MyTimeUtil2.END_TIME) { MyTimeUtil2.END_TIME = endTime; } System.out.println("Thread name:" + Thread.currentThread().getName() + " user time:" + (endTime - startTime)); } } class MyTimeUtil2 { public static long START_TIME = 0; public static long END_TIME = 0; }
输出:
Thread name:Thread-0 user time:3002
Thread name:Thread-1 user time:4002
application use time:4002
结果跟上面的差不多,基本认为是一样的
3.思考
虽然上面的方法能够缓解同步方法时所出现的问题,但是还没有根本解决,也暂时不可能解决,因此,除了上面的方法,我们还有:
(1)降低业务复杂度,从业务的角度去优化(先跳出技术的角度)
(2)增强硬件设置(跳出软件的角度)
(3)增加网络(跳出软件的角度)
(4)优化代码
总结:这一章节我们讨论了使用同步代码块缓解同步方法的隐患。
这一章节就到这里,谢谢
------------------------------------------------------------------------------------
我的github:https://github.com/raylee2015/DeepIntoThread
目录:http://blog.csdn.net/raylee2007/article/details/51204573
时间: 2024-10-11 01:44:18