从头认识多线程-2.20 synchronized同步方法的无限等待与解决方法

这一章节我们讨论一下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:https://github.com/raylee2015/DeepIntoThread


目录:http://blog.csdn.net/raylee2007/article/details/51204573


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值