您好,欢迎来到锐游网。
搜索
您的当前位置:首页从头认识多线程-2.20 synchronized同步方法的无限等待与解决方法

从头认识多线程-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:



因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- ryyc.cn 版权所有

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务