这一章节我们讨论一下synchronized同步方法的无限等待与解决方法。
1.synchronized同步方法的无限等待
package com.ray.deepintothread.ch02.topic_20;
/**
*
* @author RayLee
*
*/
public class InfiniteWait {
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();
}
}
class ThreadOne implements Runnable {
private MyService myService;
public ThreadOne(MyService myService) {
this.myService = myService;
}
@Override
public void run() {
try {
myService.updateA();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class ThreadTwo implements Runnable {
private MyService myService;
public ThreadTwo(MyService myService) {
this.myService = myService;
}
@Override
public void run() {
try {
myService.updateB();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class MyService {
private static int id = 0;
// 死循环或者不停的长连接
public synchronized void updateA() throws InterruptedException {
while (true) {
}
}
public synchronized void updateB() throws InterruptedException {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " " + id++);
Thread.sleep(100);
}
}
}
(无)
上面的例子由于线程1一直持有对象的锁,因此线程2无论如何都进不去方法里面。
2.解决方法
(1)使用同步代码块
package com.ray.deepintothread.ch02.topic_20;
/**
*
* @author RayLee
*
*/
public class SolutionOfInfiniteWait {
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();
}
}
class ThreadThree implements Runnable {
private MyService2 myService;
public ThreadThree(MyService2 myService) {
this.myService = myService;
}
@Override
public void run() {
try {
myService.updateA();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class ThreadFour implements Runnable {
private MyService2 myService;
public ThreadFour(MyService2 myService) {
this.myService = myService;
}
@Override
public void run() {
try {
myService.updateB();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class MyService2 {
private static int id = 0;
private static Object object1 = new Object();
private static Object object2 = new Object();
public void updateA() throws InterruptedException {
synchronized (object1) {
while (true) {
}
}
}
public synchronized void updateB() throws InterruptedException {
synchronized (object2) {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " " + id++);
Thread.sleep(100);
}
}
}
}
Thread-1 0
Thread-1 1
Thread-1 2
Thread-1 3
Thread-1 4
虽然这个代码清单里面线程2能够进去方法里面,但是线程1所造成的无限等待还是没有解决,而我们平常的服务器最怕就是这种长连接,因为它占掉服务器非常多的资源,不能够有效释放
(2)增加超时计数器
package com.ray.deepintothread.ch02.topic_20;
/**
*
* @author RayLee
*
*/
public class SolutionOfInfiniteWait2 {
public static void main(String[] args) throws InterruptedException {
MyService3 myService = new MyService3();
ThreadFive threadFive = new ThreadFive(myService);
Thread thread = new Thread(threadFive);
thread.start();
ThreadSix threadSix = new ThreadSix(myService);
Thread thread2 = new Thread(threadSix);
thread2.start();
}
}
class ThreadFive implements Runnable {
private MyService3 myService;
public ThreadFive(MyService3 myService) {
this.myService = myService;
}
@Override
public void run() {
try {
myService.updateA();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class ThreadSix implements Runnable {
private MyService3 myService;
public ThreadSix(MyService3 myService) {
this.myService = myService;
}
@Override
public void run() {
try {
myService.updateB();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class MyService3 {
private int id = 0;
private Object object1 = new Object();
private Object object2 = new Object();
public void updateA() throws InterruptedException {
//计数器
int count = 0;
synchronized (object1) {
while (true) {
count++;
if (count > 3) {
System.out.println(Thread.currentThread().getName() + " get out");
break;
} else {
Thread.sleep(100);
}
}
}
}
public synchronized void updateB() throws InterruptedException {
synchronized (object2) {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " " + id++);
Thread.sleep(100);
}
}
}
}
Thread-1 0
Thread-1 1
Thread-1 2
Thread-0 get out
Thread-1 3
Thread-1 4
从输出我们可以看见,线程0已经在某个边界的时候,通过计数器的超时得到了释放。
总结:这一章节主要讨论了synchronized同步方法的无限等待与解决方法。
这一章节就到这里,谢谢
------------------------------------------------------------------------------------
我的github:
因篇幅问题不能全部显示,请点此查看更多更全内容