【高并发系列】15、线程阻塞工具类 LockSupport

1、定时阻塞

java.util.concurrent.locks.LockSupport可以在线程内任意位置让线程阻塞;

与Thread.suspend()方法比,弥补了由于resume()方法在suspend()方法之前发生而导致线程无法继续执行的情况;

与Object.wait()方法比,不需要首先获得某个对象的锁,也不会抛出InterruptedException异常;

使用LockSupport重写suspend()方法永久卡死线程的例子,请见 ==>> 

【高并发系列】3、线程那些事儿 - 5、挂起suspend()和继续执行resume()线程

现修改如下

public class LockSupportDemo {
	public static Object lock = new Object();
	private static ChangeObjectThread t1 = new ChangeObjectThread("t1");
	private static ChangeObjectThread t2 = new ChangeObjectThread("t2");
	public static class ChangeObjectThread extends Thread {
		public ChangeObjectThread(String name) {
			super.setName(name);
		}

		@Override
		public void run() {
			synchronized (lock) {
				System.out.println("In " + getName());
				LockSupport.park();
			}
		}
	}
	public static void main(String[] args) throws InterruptedException {
		t1.start();
		Thread.sleep(2000);
		t2.start();
		LockSupport.unpark(t1);
		LockSupport.unpark(t2);
		t1.join();
		t2.join();
	}
}

把suspend()方法和resume()方法用park()和unpark()方法替换;

无法保证unpark()方法发生在park()方法之后,但是执行发现可以正常结束,不会出现suspend()方法线程永远挂起的情况;

LockSupport类使用类似信号量Semaphore的机制;为每一个线程准备了一个许可;如果许可可用,park()方法立即返回,并且消费这个许可(将许可变为不可用);如果许可不可用,就会阻塞,而unpark()方法使一个许可变为可用;

与信号量区别在于,这个许可不能累加,每个线程只有一个许可;

2、中断响应

LockSupport不会抛出InterruptedException异常,但可以从Thread.interrupted()等方法中获得中断标记;

t1获得lock锁,park()阻塞t1,t1.interrupt()被中断,t1马上响应并返回,释放lock锁;t2获得lock锁,park()方法阻塞后,unpark()继续执行,退出程序;

public class LockSupportIntDemo {
	public static Object lock = new Object();
	private static ChangeObjectThread t1 = new ChangeObjectThread("t1");
	private static ChangeObjectThread t2 = new ChangeObjectThread("t2");
	public static class ChangeObjectThread extends Thread {
		public ChangeObjectThread(String name) {
			super.setName(name);
		}
		@Override
		public void run() {
			synchronized (lock) {
				System.out.println("In " + getName());
				LockSupport.park();
				if (Thread.interrupted()) {
					System.out.println(getName() + " is interrupted.");
				}
			}
			System.out.println(getName() + " is finished.");
		}
	}
	public static void main(String[] args) throws InterruptedException {
		t1.start();
		TimeUnit.MILLISECONDS.sleep(1000);
		t2.start();
		t1.interrupt();
		TimeUnit.MILLISECONDS.sleep(1000);
		LockSupport.unpark(t2);
	}
}

console

In t1
t1 is interrupted.
t1 is finished.
In t2
t2 is finished.

猜你喜欢

转载自blog.csdn.net/hellboy0621/article/details/87245708
今日推荐