这一章节我们来讨论一下缓解同步方法的隐患-同步代码块。
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