Java~多线程ReentrantLock类常用的十四个方法, 使用Condition实现多线程的顺序执行
程序员文章站
2022-05-03 20:57:38
...
文章目录
- 方法getHoldCount()
- 方法getQueueLength()
- 方法getWaitQueueLength()
- 方法hasQueuedThread()和方法hasQueuedThreads()
- 方法hasWaiters()
- 方法isFair()
- 方法isHeldByCurrentThread()
- 方法isLocked()
- 方法lockInterruptibly()、tryLock()和tryLock(long timeout,TimeUnit unit)
- 方法awaitUninterruptibly()
- 方法await(time) 和 awaitUntil()
- 使用Condition实现多线程的顺序执行
方法getHoldCount()
- 该方法的作用是查询当前被这个锁锁定的线程个数, 也就是这个锁执行lock的次数
public class Demo1 {
public static void main(String[] args) {
ReentrantLock reentrantLock = new ReentrantLock();
Thread thread = new Thread() {
@Override
public void run() {
method1();
}
public void method1() {
reentrantLock.lock();
System.out.println(Thread.currentThread().getName() + " " +
reentrantLock.getHoldCount());
method2();
reentrantLock.unlock();
}
public void method2() {
reentrantLock.lock();
System.out.println(Thread.currentThread().getName() + " " +
reentrantLock.getHoldCount());
reentrantLock.unlock();
}
};
thread.start();
}
}
方法getQueueLength()
- 该方法返回的是想要获取这个锁的线程个数
- 比如有5个线程,1个线程首先执行await()方法,那么在调用getQueueLength()方法后返回值是4,说明有4个线程同时在等待lock 的释放。
public class Demo2 {
public static void main(String[] args) throws InterruptedException {
ReentrantLock reentrantLock = new ReentrantLock();
Runnable runnable = new Runnable() {
@Override
public void run() {
reentrantLock.lock();
try {
Thread.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
}
};
Thread[] threads = new Thread[5];
for (int i = 0; i < 5; i++) {
threads[i] = new Thread(runnable);
}
for (int i = 0; i < 5; i++) {
threads[i].start();
}
Thread.sleep(100);
System.out.println(reentrantLock.getQueueLength());
}
}
方法getWaitQueueLength()
- 方法int getWaitfQueueI engh(Condition condition)的作用是返回等待与此锁定相关的给定条件Condition的线程估计数,比如有5个线程,每个线程都执行了同一个condition对象的await()方法,则调用getWaitQueueLengh(Condition condition)方法时返回的int值是5。
- 也就是同一个condition执行await的次数, 也就是目前有多少个线程处于某一个condition的await下
public class Demo3 {
public static void main(String[] args) {
ReentrantLock reentrantLock = new ReentrantLock();
Condition condition = reentrantLock.newCondition();
Runnable runnable = new Runnable() {
@Override
public void run() {
reentrantLock.lock();
try {
System.out.println(reentrantLock.getWaitQueueLength(condition));
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread[] threads = new Thread[5];
for (int i = 0; i < 5; i++) {
threads[i] = new Thread(runnable);
}
for (int i = 0; i < 5; i++) {
threads[i].start();
}
}
}
方法hasQueuedThread()和方法hasQueuedThreads()
- 方法boolean hasQueuedThread(Thread thread) 的作用是查询指定的线程是否正在等待获取此锁定。 也就是查看指定线程想要获取锁.
- 方法boolean hasQueuedThreads()的作用是查询是否有线程正在等待获取此锁定。也就是这个不指定了, 而是只要有想要这把锁的就返回true
public class Demo4 {
public static void main(String[] args) throws InterruptedException {
ReentrantLock reentrantLock = new ReentrantLock();
Runnable runnable = new Runnable() {
@Override
public void run() {
reentrantLock.lock();
try {
Thread.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
}
};
Thread a = new Thread(runnable);
a.start();
Thread.sleep(100);
Thread b = new Thread(runnable);
b.start();
Thread.sleep(100);
System.out.println("a需要吗? " + reentrantLock.hasQueuedThread(a));
System.out.println("b需要吗? " + reentrantLock.hasQueuedThread(b));
System.out.println("有需要吗? " + reentrantLock.hasQueuedThreads());
}
}
方法hasWaiters()
- 方法boolean hasWaiters(Condition condition)的作用是查询是否有线程正在等待与此锁定有关的condition条件。
- 也就是在这个condition下有没有线程执行了await还没有唤醒
- 这个方法必须在加锁的情况下使用不然没有对象监视器的所有权, 从而抛出IllegalMonitorStateException
public class Demo5 {
public static void main(String[] args) throws InterruptedException {
ReentrantLock reentrantLock = new ReentrantLock();
Condition condition = reentrantLock.newCondition();
Thread thread = new Thread() {
@Override
public void run() {
reentrantLock.lock();
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
}
};
thread.start();
Thread.sleep(100);
//注意使用这个方法必须在lock下使用, 不然会没有这个对象监视器的所有权而抛出异常
reentrantLock.lock();
System.out.println("有没有等待signal的线程 " + reentrantLock.hasWaiters(condition));
reentrantLock.unlock();
}
}
方法isFair()
- 方法boolean isFair()的作用是判断是不是公平锁。 这个很简单 就不做演示了
方法isHeldByCurrentThread()
- 方法boolean isHeldByCurrentThread()的作用是查询当前线程是否保持此锁定。
- 也就是这个线程是否执行了lock
public class Demo6 {
public static void main(String[] args) {
ReentrantLock reentrantLock = new ReentrantLock();
System.out.println(reentrantLock.isHeldByCurrentThread());
reentrantLock.lock();
System.out.println(reentrantLock.isHeldByCurrentThread());
reentrantLock.unlock();
}
}
方法isLocked()
- 方法boolean isLocked()的作用是查询此锁定是否由任意线程保持。
- 也就是这把锁是否已经执行了lock
public class Demo7 {
public static void main(String[] args) throws InterruptedException {
ReentrantLock reentrantLock = new ReentrantLock();
System.out.println(reentrantLock.isLocked());
Thread thread = new Thread() {
@Override
public void run() {
reentrantLock.lock();
System.out.println("执行lock");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("释放lock");
reentrantLock.unlock();
}
}
};
thread.start();
for (int i = 0; i < 10; i++) {
System.out.println(reentrantLock.isLocked());
Thread.sleep(200);
}
}
}
方法lockInterruptibly()、tryLock()和tryLock(long timeout,TimeUnit unit)
- 这三个方法大同小异
- 方法void locklnterruptibly()的作用是:如果当前线程未被中断,则获取锁定,如果已经被中断则出现异常。 也就是我们在普通使用lock方法加锁时, 如果这个线程被中断了是不会抛出异常的, 而使用locklnterruptibly方法加锁如果这个线程中断了是会抛出异常的
- 方法boolean tryLock()的作用是,仅在调用时锁定未被另一个线程保持的情况下,才获取该锁定。 本意就是我尝试去获取锁, 如果没人拿我就拿, 如果有人拿我就不要这把锁了
- 方法boolean tryLock(long timeout, TimeUnit unit)的作用是,如果锁定在给定等待时间内没有被另一个线程保持,且当前线程未被中断,则获取该锁定。 也就是我会支持一段时间去尝试那这个把锁, 在这个时间段里, 我没拿到我就不要了
public class Service1 {
private ReentrantLock reentrantLock = new ReentrantLock();
public void method() {
try {
if (reentrantLock.tryLock(3, TimeUnit.SECONDS)) {
System.out.println(Thread.currentThread().getName() + " " +
"获取锁的时间:" + System.currentTimeMillis());
Thread.sleep(10000);
} else {
System.out.println(Thread.currentThread().getName() + " 没有获得锁");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (reentrantLock.isHeldByCurrentThread()) {
reentrantLock.unlock();
}
}
}
}
public class Demo1 {
public static void main(String[] args) throws InterruptedException {
Service1 service1 = new Service1();
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " 执行method时间" +
System.currentTimeMillis());
service1.method();
}
};
Thread a = new Thread(runnable, "A");
a.start();
Thread b = new Thread(runnable, "B");
b.start();
}
}
方法awaitUninterruptibly()
- 我没在普通使用await的时候, 如果这个线程中断了, 就会抛出异常, 但是使用awaitUninterruptibly()即使在等待中的线程被打断了, 也不会抛出异常
方法await(time) 和 awaitUntil()
- 这俩个方法和synchronized的wait(long)和相似, 就是wait等待一段时间, 可以提前唤醒, 也可以等时间到了自动唤醒.
public class Demo2 {
public static void main(String[] args) throws InterruptedException {
ReentrantLock reentrantLock = new ReentrantLock();
Condition condition = reentrantLock.newCondition();
reentrantLock.lock();
System.out.println(Thread.currentThread().getName() + " 开始时间:" +
System.currentTimeMillis());
condition.await(3, TimeUnit.SECONDS);
System.out.println(Thread.currentThread().getName() + " 结束时间:" +
System.currentTimeMillis());
reentrantLock.unlock();
}
}
使用Condition实现多线程的顺序执行
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
* Created with IntelliJ IDEA.
* Description: If you don't work hard, you will a loser.
* User: Listen-Y.
* Date: 2020-10-10
* Time: 18:25
*/
public class Run {
private static ReentrantLock reentrantLock = new ReentrantLock();
//关键变量
volatile private static int key = 1;
//三个condition保证三种线程 挨个运行
private static Condition conditionA = reentrantLock.newCondition();
private static Condition conditionB = reentrantLock.newCondition();
private static Condition conditionC = reentrantLock.newCondition();
public static void main(String[] args) {
//实现三个runnable任务
Runnable runnableA = new Runnable() {
@Override
public void run() {
try {
reentrantLock.lock();
while (key != 1) {
conditionA.await();
}
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
key = 2;
//唤醒所有B线程
conditionB.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
}
};
Runnable runnableB = new Runnable() {
@Override
public void run() {
try {
reentrantLock.lock();
while (key != 2) {
conditionB.await();
}
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
key = 3;
//唤醒所有C线程
conditionC.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
}
};
Runnable runnableC = new Runnable() {
@Override
public void run() {
try {
reentrantLock.lock();
while (key != 3) {
conditionC.await();
}
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
key = 1;
//唤醒所有A线程
conditionA.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
}
};
//创建多个线程
Thread[] threadsA = new Thread[5];
Thread[] threadsB = new Thread[5];
Thread[] threadsC = new Thread[5];
for (int i = 0; i < 5; i++) {
threadsA[i] = new Thread(runnableA, "ThreadA");
threadsB[i] = new Thread(runnableB, "ThreadB");
threadsC[i] = new Thread(runnableC, "ThreadC");
}
//启动所有线程
for (int i = 0; i < 5; i++) {
threadsA[i].start();
threadsB[i].start();
threadsC[i].start();
}
}
}