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.