J.U.C并发编程包详解 (1) Lock接口
一、Lock锁接口
定义Java中Java.Util.concurrent 中锁 Lock 的基本接口方法
二、Lock 接口方法
Lock 接口有以下几个方法
public interface Lock { void lock(); void lockInterruptibly() throws InterruptedException; boolean tryLock(); boolean tryLock(long time, TimeUnit unit) throws InterruptedException; void unlock(); Condition newCondition(); }
lock() 是一直等到获取锁
void lock();
tryLock() 是尝试获取锁
boolean tryLock();
tryLock(Long time, TimeUnit time) 设置尝试在某个时间内获取锁,过了这个时间就不尝试获取了
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
lockInterruptibly 中止锁
void lockInterruptibly() throws InterruptedException;
unlock( ) 解锁
unlock();
newCondition 稍后解释
Condition newCondition();
三、lock 使用
Lock的使用,通过实现Lock接口的 ReentranLock 类来实现;
3.1、lock()
import org.apache.tomcat.jni.Time; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class LockDemo { static Lock lock = new ReentrantLock(); public static void main(String[] args) throws Exception{ lock.lock(); Thread th = new Thread(new Runnable() { @Override public void run() { System.out.println("========= Try to get lock : " + System.currentTimeMillis());
// lock 会一直等到线程可以拿到锁为止再运行 lock.lock(); System.out.println("========= Get lock : " + System.currentTimeMillis()); } }); System.out.println("========= Begin : " + System.currentTimeMillis()); th.start(); Thread.sleep(2000); System.out.println("========= After sleep: " + System.currentTimeMillis()); lock.unlock(); System.out.println("========= End : " + System.currentTimeMillis()); } }
打印
========= Begin : 1596676916634
========= Try to get lock : 1596676916636
========= After sleep: 1596676918636
========= Get lock : 1596676918637
========= End : 1596676918637
代码演示图
说明:
(1)主线程 A 先获取到锁;
(2)启动另外一个线程 B;
(3)线程 B 尝试获取 锁,获取不到,进入锁池, 等待获取锁,运行跳回主线程A;
(4)线程 A 进入休眠 2 秒;
(5)线程 A 休眠完,解开锁,运行并跳回线程 B;
(6) 线程 B 获取锁;
(7)程序结束
3.2、tryLock()
public class LockDemo { static Lock lock = new ReentrantLock(); public static void main(String[] args) throws Exception{ lock.lock(); Thread th = new Thread(new Runnable() { @Override public void run() { System.out.println("========= Try to get lock : " + System.currentTimeMillis()); boolean get = lock.tryLock();
//这里将显示失败, 因为主线程没有释放锁,所以这个线程获取不到 System.out.println("========= Get lock : " + get ); System.out.println("======== Get lock Time : " + System.currentTimeMillis()); } }); System.out.println("========= Begin : " + System.currentTimeMillis()); th.start(); Thread.sleep(2000); System.out.println("========= After sleep: " + System.currentTimeMillis()); lock.unlock(); System.out.println("========= End : " + System.currentTimeMillis()); } }
打印
========= Begin : 1596678142300
========= Try to get lock : 1596678142300
========= Get lock : false
======== Get lock Time : 1596678142301
========= After sleep: 1596678144300
========= End : 1596678144300
可以看到,由于这个方法,线程没有进入锁池等待获取锁,只要没有获取到锁就不等待了。
3.3、tryLock(Long time, TimeUnit time)
public class LockDemo { static Lock lock = new ReentrantLock(); public static void main(String[] args) throws Exception{ lock.lock(); Thread th = new Thread(new Runnable() { @Override public void run() { System.out.println("========= Try to get lock : " + System.currentTimeMillis()); boolean get = false; // 线程在这里等 3秒, 获取到锁
try { get = lock.tryLock(3000, TimeUnit.SECONDS); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("========= Get lock : " + get ); System.out.println("========= Get lock Time : " + System.currentTimeMillis()); } }); System.out.println("========= Begin : " + System.currentTimeMillis()); th.start(); Thread.sleep(2000); System.out.println("========= After sleep: " + System.currentTimeMillis()); lock.unlock(); System.out.println("========= End : " + System.currentTimeMillis()); } }
打印
========= Begin : 1596678402148
========= Try to get lock : 1596678402161
========= After sleep: 1596678404148
========= End : 1596678404148
========= Get lock : true
========= Get lock Time : 1596678404148
3.4 lockInterruptibly( )
线程B 等到 线程B调用 interrupt() 方法就不等了
public class InterrupteLockDemo { static Lock lock = new ReentrantLock(); public static void main(String[] args) throws Exception{ lock.lock(); Thread th = new Thread(new Runnable() { @Override public void run() { System.out.println("========= Try to get lock : " + System.currentTimeMillis()); try {
/*等待,获取锁,直到线程调用 interrupt(), 就不等了*/ lock.lockInterruptibly(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("========= Get lock Time : " + System.currentTimeMillis()); } }); System.out.println("========= Begin : " + System.currentTimeMillis()); th.start(); Thread.sleep(2000); System.out.println("========= After sleep: " + System.currentTimeMillis()); th.interrupt(); Thread.sleep(2000); System.out.println("========= End : " + System.currentTimeMillis()); } }
打印
========= Begin : 1596683400461
========= Try to get lock : 1596683400462
========= After sleep: 1596683402477
========= Get lock Time : 1596683402479
java.lang.InterruptedException
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:898)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)
at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
at com.jm.lock.InterrupteLockDemo$1.run(InterrupteLockDemo.java:21)
at java.lang.Thread.run(Thread.java:748)
========= End : 1596683404478
3.5 new Condition
public class newCondition { static Lock lock = new ReentrantLock(); static private Condition condition = lock.newCondition(); public static void main(String[] args) throws Exception{ Thread th = new Thread(new Runnable() { @Override public void run() { lock.lock(); try { System.out.println("当前线程 获得锁 : " + System.currentTimeMillis()); condition.await();//挂起线程 System.out.println("当前线程 开始执行: " + System.currentTimeMillis()); } catch (InterruptedException e) { lock.unlock(); e.printStackTrace(); } System.out.println("========= Get lock Time : " + System.currentTimeMillis()); } }); System.out.println("========= Begin : " + System.currentTimeMillis()); th.start(); Thread.sleep(2000); System.out.println("========= After sleep: " + System.currentTimeMillis()); lock.lock(); condition.signal(); lock.unlock(); System.out.println("========= End : " + System.currentTimeMillis()); } }