Thread之ReentrantLock与Condition


在这里插入图片描述

简单演示

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Demo01 {
    
    
    public static void main(String[] args) {
    
    
        Lock lock = new ReentrantLock();
        //模拟3个线程
        Demo01Thread threadA = new Demo01Thread(lock);
        Demo01Thread threadB = new Demo01Thread(lock);
        Demo01Thread threadC = new Demo01Thread(lock);
        //设置名称
        threadA.setName("线程A");
        threadB.setName("线程B");
        threadC.setName("线程C");
        //启动
        threadA.start();
        threadB.start();
        threadC.start();
    }
}
class Demo01Thread extends Thread{
    
    
    private Lock lock;
    //通过构造方法传递锁对象
    public Demo01Thread(Lock lock){
    
    
        this.lock = lock;
    }
    @Override
    public void run() {
    
    
        //加上锁
        lock.lock();
        for (int i = 0; i < 3; i++) {
    
    
            System.out.println(Thread.currentThread().getName()+" :---:"+i);
        }
        //解开锁
        lock.unlock();
    }
}

运行结果

在这里插入图片描述
在这里插入图片描述

synchronized 进行同步互斥控制

import lombok.SneakyThrows;

/**
 * synchronized 进行同步互斥控制
 * @author layman
 * @date 2021/2/9
 */
public class Demo02 {
    
    
    public static void main(String[] args) {
    
    
        Demo02Service service = new Demo02Service();
        Demo02ThreadA threadA = new Demo02ThreadA(service);
        Demo02ThreadB threadB = new Demo02ThreadB(service);

        threadA.setName("线程A");
        threadB.setName("线程B");

        threadA.start();
        threadB.start();
    }
}
class Demo02Service{
    
    
    public synchronized void methodA() throws InterruptedException {
    
    
        System.out.println(Thread.currentThread().getName()+" 开始执行methodA方法:"+System.currentTimeMillis());
        Thread.sleep(3000L);
        System.out.println(Thread.currentThread().getName()+" 结束执行methodA方法:"+System.currentTimeMillis());
    }
    public synchronized void methodB() throws InterruptedException {
    
    
        System.out.println(Thread.currentThread().getName()+" 开始执行methodB方法:"+System.currentTimeMillis());
        Thread.sleep(3000L);
        System.out.println(Thread.currentThread().getName()+" 结束执行methodB方法:"+System.currentTimeMillis());
    }
}
class Demo02ThreadA extends  Thread{
    
    
    private Demo02Service service;
    public Demo02ThreadA(Demo02Service service){
    
    
        this.service = service;
    }
    @SneakyThrows
    @Override
    public void run() {
    
    
        service.methodA();
    }
}
class Demo02ThreadB extends  Thread{
    
    
    private Demo02Service service;
    public Demo02ThreadB(Demo02Service service){
    
    
        this.service = service;
    }
    @SneakyThrows
    @Override
    public void run() {
    
    
        service.methodB();
    }
}

运行结果

在这里插入图片描述

修改为ReentrantLock进行同步互斥

public class Demo02 {
    
    
    public static void main(String[] args) {
    
    
        Demo02Service service = new Demo02Service();
        Demo02ThreadA threadA = new Demo02ThreadA(service);
        Demo02ThreadB threadB = new Demo02ThreadB(service);

        threadA.setName("线程A");
        threadB.setName("线程B");

        threadA.start();
        threadB.start();
    }
}
class Demo02Service{
    
    
    private SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd HH:mm:ss");
    private Lock lock = new ReentrantLock();
    public /*synchronized*/ void methodA() throws InterruptedException {
    
    
        lock.lock();
        System.out.println(Thread.currentThread().getName()+" 开始执行methodA方法:"+sdf.format(new Date(System.currentTimeMillis())));
        Thread.sleep(3000L);
        System.out.println(Thread.currentThread().getName()+" 结束执行methodA方法:"+sdf.format(new Date(System.currentTimeMillis())));
        lock.unlock();
    }
    public /*synchronized*/ void methodB() throws InterruptedException {
    
    
        lock.lock();
        System.out.println(Thread.currentThread().getName()+" 开始执行methodB方法:"+sdf.format(new Date(System.currentTimeMillis())));
        Thread.sleep(3000L);
        System.out.println(Thread.currentThread().getName()+" 结束执行methodB方法:"+sdf.format(new Date(System.currentTimeMillis())));
        lock.unlock();
    }
}
class Demo02ThreadA extends  Thread{
    
    
    private Demo02Service service;
    public Demo02ThreadA(Demo02Service service){
    
    
        this.service = service;
    }
    @SneakyThrows
    @Override
    public void run() {
    
    
        service.methodA();
    }
}
class Demo02ThreadB extends  Thread{
    
    
    private Demo02Service service;
    public Demo02ThreadB(Demo02Service service){
    
    
        this.service = service;
    }
    @SneakyThrows
    @Override
    public void run() {
    
    
        service.methodB();
    }
}

运行结果

在这里插入图片描述

结论

  • 调用lock方法的线程会持有对象锁,其他线程只能等待锁被释放(unlock方法)才可以再次争抢锁。
  • lock和synchronized一样,都是顺序进行

ReentrantLock与condition实现wait和notify

在这里插入图片描述

import lombok.SneakyThrows;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Demo03 {
    
    
    public static void main(String[] args) throws InterruptedException {
    
    
        Demo03Service service = new Demo03Service();
        Demo03Thread t = new Demo03Thread(service);

        t.start();
        Thread.sleep(2000L);
        service.signal();
    }
}
class Demo03Service{
    
    
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    private SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd HH:mm:ss");
    //等待方法
    public void await() throws InterruptedException {
    
    
        lock.lock();
        System.out.println("await方法开始于:" + sdf.format(new Date(System.currentTimeMillis())));
        //该方法需在同步代码块中执行,否则会抛出IllegalMonitorStateException
        condition.await();
        System.out.println("await方法结束于:" + sdf.format(new Date(System.currentTimeMillis())));
        lock.unlock();
    }
    //通知方法
    public void signal() {
    
    
        lock.lock();
        System.out.println("signal方法开始于:" + sdf.format(new Date(System.currentTimeMillis())));
        condition.signal();
        lock.unlock();
    }
}
class Demo03Thread extends  Thread{
    
    
    private Demo03Service service;
    public Demo03Thread(Demo03Service service){
    
    
        this.service = service;
    }
    @SneakyThrows
    @Override
    public void run() {
    
    
        service.await();
    }
}

ReentrantLock与condition实现选择性唤醒

import lombok.SneakyThrows;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Demo04 {
    
    
    public static void main(String[] args) throws InterruptedException {
    
    
        Demo04Service service = new Demo04Service();
        Demo04ThreadA threadA = new Demo04ThreadA(service);
        //A进入等待状态
        threadA.start();
        Demo04ThreadB threadB = new Demo04ThreadB(service);
        //B进入等待状态
        threadB.start();
        Thread.sleep(3000L);
        //只唤醒A
        service.signal_A();
    }
}
class Demo04Service{
    
    
    private Lock lock = new ReentrantLock();
    private Condition conditionA = lock.newCondition();
    private Condition conditionB = lock.newCondition();
    private SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd HH:mm:ss");
    //等待方法A
    public void awaitA() throws InterruptedException {
    
    
        lock.lock();
        System.out.println("awaitA方法开始于:" + sdf.format(new Date(System.currentTimeMillis())));
        conditionA.await();
        System.out.println("awaitA方法结束于:" + sdf.format(new Date(System.currentTimeMillis())));
        lock.unlock();
    }
    //等待方法B
    public void awaitB() throws InterruptedException {
    
    
        lock.lock();
        System.out.println("awaitB方法开始于:" + sdf.format(new Date(System.currentTimeMillis())));
        conditionB.await();
        System.out.println("awaitB方法结束于:" + sdf.format(new Date(System.currentTimeMillis())));
        lock.unlock();
    }
    //通知方法A
    public void signal_A() {
    
    
        lock.lock();
        System.out.println("signal_A方法开始于:" + sdf.format(new Date(System.currentTimeMillis())));
        //唤醒A
        conditionA.signal();
        lock.unlock();
    }
    //通知方法B
    public void signal_B() {
    
    
        lock.lock();
        System.out.println("signal_B方法开始于:" + sdf.format(new Date(System.currentTimeMillis())));
        //唤醒B
        conditionB.signal();
        lock.unlock();
    }
}
class Demo04ThreadA extends  Thread{
    
    
    private Demo04Service service;
    public Demo04ThreadA(Demo04Service service){
    
    
        this.service = service;
    }
    @SneakyThrows
    @Override
    public void run() {
    
    
        service.awaitA();
    }
}
class Demo04ThreadB extends  Thread{
    
    
    private Demo04Service service;
    public Demo04ThreadB(Demo04Service service){
    
    
        this.service = service;
    }
    @SneakyThrows
    @Override
    public void run() {
    
    
        service.awaitB();
    }
}

运行结果

在这里插入图片描述

结论

在这里插入图片描述

ReentrantLock与condition实现生产者与消费者

生产者与消费者(一对一&多对多)

import lombok.SneakyThrows;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 演示一对一和多对多
 * @author layman
 */
public class Demo05 {
    
    
    public static void main(String[] args) {
    
    
        Demo05Service service = new Demo05Service();
        //生产-消费(一对一关系)
        /*Demo05Producer producer = new Demo05Producer(service);
        Demo05Consumer consumer = new Demo05Consumer(service);
        producer.start();
        consumer.start();*/
        生产-消费(多对多关系)
        int size = 5;
        Demo05Producer[] producers = new Demo05Producer[size];
        Demo05Consumer[] consumers = new Demo05Consumer[size];

        for (int i = 0; i < size; i++) {
    
    
            char name = (char)('A'+i);
            producers[i] = new Demo05Producer(service);
            producers[i].setName("生产者"+name);
            producers[i].start();

            consumers[i] = new Demo05Consumer(service);
            consumers[i].setName("消费者"+name);
            consumers[i].start();
        }
    }
}
class Demo05Service{
    
    
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    private String value = "";

    public void setValue() throws InterruptedException {
    
    
        lock.lock();
        while(!"".equals(value)){
    
    
            //如果有值,就等待消费
            System.out.println(Thread.currentThread().getName()+" 进入等待状态 ");
            condition.await();
        }
        //如果没有值,就生产值,然后通知消费者消费
        value = System.currentTimeMillis()+" - "+System.nanoTime();
        System.out.println(Thread.currentThread().getName()+" 生产的值: " + value);
        //Thread.sleep(500L);
        //condition.signal();
        //多生产者与多消费者模式需要唤醒所有等待的线程,否则会唤醒消费者,进入无限等待状态
        condition.signalAll();
        lock.unlock();
    }
    public void getValue() throws InterruptedException {
    
    
        lock.lock();
        while(!"".equals(value)){
    
    
            //如果有值,就消费,然后通知生产者生产
            System.out.println(Thread.currentThread().getName()+" 消费的值: " + value);
            value = "";
            //Thread.sleep(500L);
            //condition.signal();
            //多生产者与多消费者模式需要唤醒所有等待的线程,否则会唤醒消费者,进入无限等待状态
            condition.signalAll();
        }
        //如果没有值,就等待生产者生产值
        System.out.println(Thread.currentThread().getName()+" 进入等待状态 ");
        condition.await();
        lock.unlock();
    }
}
class Demo05Producer extends Thread{
    
    
    private Demo05Service service;

    public Demo05Producer(Demo05Service service){
    
    
        this.service = service;
    }

    @SneakyThrows
    @Override
    public void run() {
    
    
        while(true){
    
    
            service.setValue();
        }
    }
}
class Demo05Consumer extends Thread{
    
    
    private Demo05Service service;

    public Demo05Consumer(Demo05Service service){
    
    
        this.service = service;
    }

    @SneakyThrows
    @Override
    public void run() {
    
    
        while(true){
    
    
            service.getValue();
        }
    }
}

ReentrantLock之公平锁和非公平锁

在这里插入图片描述

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author layman
 * @date 2021/2/9
 */
public class Demo06 {
    
    
    public static void main(String[] args) {
    
    
        Demo06Service service = new Demo06Service(true);
        int size = 20;
        Demo06Thread[] threads = new Demo06Thread[size];
        for (int i = 0; i < size; i++) {
    
    
            threads[i] = new Demo06Thread(service);
        }
        for (int i = 0; i < size; i++) {
    
    
            threads[i].start();
        }
    }
}
class Demo06Service{
    
    
    private Lock lock;
    public Demo06Service(boolean isFair){
    
    
        //true的ReentrantLock是公平锁,反之为非公平锁
        this.lock = new ReentrantLock(isFair);
    }
    public void doSomething(){
    
    
        lock.lock();
        System.out.println(Thread.currentThread().getName()+" 被锁定了");
        lock.unlock();
    }
}
class Demo06Thread extends Thread{
    
    
    private Demo06Service service;
    public Demo06Thread(Demo06Service service){
    
    
        this.service = service;
    }
    @Override
    public void run() {
    
    
        service.doSomething();
    }
}

猜你喜欢

转载自blog.csdn.net/single_0910/article/details/113769561