用例 1
一个用例是完全避免运行线程。如下例所示,例如一个非常严格的互联网热点,您一次只能访问一个网页,其他请求被取消。
使用synchronized 你不能取消它,因为它一直等到它可以获取锁。所以tryLock 只是让你灵活地取消某些东西或运行其他行为。
package Concurrency;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LimitedHotspotDemo
{
private static Lock webAccessLock = new ReentrantLock();
private static class AccessUrl implements Runnable
{
private String url;
public AccessUrl(String url)
{
this.url = url;
}
@Override
public void run()
{
if(webAccessLock.tryLock()) {
System.out.println("Begin request for url " + url);
try {
Thread.sleep(1500);
System.out.println("Request completed for " + url);
} catch (InterruptedException e) {
webAccessLock.unlock();
return;
} finally {
webAccessLock.unlock();
}
} else {
System.out.println("Cancelled request " + url + "; already one request running");
}
}
}
public static void main(String[] args)
{
for(String url : Arrays.asList(
"https://www.google.com/",
"https://www.microsoft.com/",
"https://www.apple.com/"
)) {
new Thread(new AccessUrl(url)).start();
}
}
}
输出:
Begin request for url https://www.microsoft.com/
Cancelled request https://www.google.com/; already one request running
Cancelled request https://www.apple.com/; already one request running
Request completed for https://www.microsoft.com/
用例 2
另一个用例是光传感器,当房间里有移动时,它会保持灯亮(使用Sensor 线程)。当房间内几秒钟内没有任何动静时,另一个线程 (TurnOffLights) 正在运行以关闭灯。
TurnOffLights 线程使用tryLock 获取锁。如果无法获得锁,则该过程延迟 500ms。最后一个Sensor线程阻塞锁5秒,之后TurnOffLights线程可以获取锁并关灯。
所以在这种情况下,TurnOffLights 线程只允许在 5 秒内没有更多信号给Sensor 时关闭灯。 TurnOffLights 线程正在使用tryLock 获取锁。
package Concurrency;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LightSensorDemo
{
private static volatile Lock lock = new ReentrantLock();
private static volatile Thread lastSignal = null;
private static Sensor sensor = new Sensor();
private static class Sensor implements Runnable
{
private static Boolean preparing = false;
public static Boolean isPreparing()
{
return preparing;
}
@Override
public void run()
{
System.out.println("Signal send " + Thread.currentThread().getName());
try {
invalidatePreviousSignalsAndSetUpCurrent();
Thread.sleep(5 * 1000);
} catch (InterruptedException e) {
//System.out.println("Signal interrupted " + Thread.currentThread().getName());
return;
} finally {
lock.unlock();
}
}
private static synchronized void invalidatePreviousSignalsAndSetUpCurrent() throws InterruptedException
{
preparing = true;
if(lastSignal != null) {
lastSignal.interrupt();
}
lastSignal = Thread.currentThread();
lock.lockInterruptibly();
preparing = false;
}
}
private static class TurnOffLights implements Runnable
{
@Override
public void run()
{
while(true) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
System.out.println("Interrupted" + this.getClass().getName());
return;
}
if (!Sensor.isPreparing()) {
if(lock.tryLock()) {
try {
System.out.println("Turn off lights");
break;
} finally {
lock.unlock();
}
} else {
System.out.println("Cannot turn off lights yet");
}
} else {
System.out.println("Cannot turn off lights yet");
}
}
}
}
public static void main(String[] args) throws InterruptedException
{
Thread turnOffLights = new Thread(new TurnOffLights());
turnOffLights.start();
//Send 40 signals to the light sensor to keep the light on
for(int x = 0; x < 10; x++) {
new Thread(sensor).start(); //some active movements
new Thread(sensor).start(); //some active movements
new Thread(sensor).start(); //some active movements
new Thread(sensor).start(); //some active movements
Thread.sleep(250);
}
turnOffLights.join();
}
}
还请注意,我使用lock.lockInterruptibly(); 来中断先前的信号。所以 5 秒倒计时总是从最后一个信号开始。
输出类似于:
...
Cannot turn off lights yet
Cannot turn off lights yet
Signal send Thread-19
Signal send Thread-20
Cannot turn off lights yet
Cannot turn off lights yet
Cannot turn off lights yet
Cannot turn off lights yet
Cannot turn off lights yet
Cannot turn off lights yet
Cannot turn off lights yet
Cannot turn off lights yet
Cannot turn off lights yet
Cannot turn off lights yet
Turn off lights
Process finished with exit code 0