java多线程核心编程技术-Lock的使用-使用ReentrantLock类

使用Reentrantlock 类

使用Reentrantlock 实现同步

package ReentrantLockTest;

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

/**
 * @author
 * @create 2020-11-19 14:41
 **/
public class MyService {
    private Lock lock  = new ReentrantLock();
    public void testMethod() {
        lock.lock();
        for (int i = 0; i < 5; i++) {
            System.out.println("ThreadNmae=" + Thread.currentThread().getName() +
                    (" " + (i +1)));
        }
        lock.unlock();
    }

}

package ReentrantLockTest;

/**
 * @author
 * @create 2020-11-19 14:46
 **/
public class MyThread extends Thread {
    private MyService service;
    public MyThread(MyService service) {
        super();
        this.service = service;
    }

    @Override
    public void run() {
        service.testMethod();
    }
}

package ReentrantLockTest;

/**
 * @author
 * @create 2020-11-19 14:48
 **/
public class Run {

    public static void main(String[] args) {
        MyService service = new MyService();
        MyThread a1 = new MyThread(service);
        MyThread a2 = new MyThread(service);
        MyThread a3 = new MyThread(service);
        MyThread a4 = new MyThread(service);
        MyThread a5 = new MyThread(service);
        a1.start();
        a2.start();
        a3.start();
        a4.start();
        a5.start();
    }
}

运行结果
在这里插入图片描述
结果可以看出
1 Reentrantlock对象的lock 方法获取锁,调用unlock 方法释放锁。
2 每个线程都是打印完成后释放锁,其他的线程继续打印。
3 线程之间的打印顺序是随机的。

使用ReentrantLock 实现同步 测试2

package ConditionTestMoreMethod;

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

/**
 * @author
 * @create 2020-11-19 15:00
 **/
public class MyService {

    private Lock lock = new ReentrantLock();
    public void methodA() {
        try {
            lock.lock();
            System.out.println("methodA begin ThreadName=" + Thread.currentThread().getName() + " time= " + System.currentTimeMillis());
            Thread.sleep(5000);
            System.out.println("methodA end ThreadName=" + Thread.currentThread().getName() + " time= " + System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        finally {
            lock.unlock();
        }
    }
    public void methodB() {
        try {
            lock.lock();
            System.out.println("methodB begin ThreadName=" + Thread.currentThread().getName() + " time= " + System.currentTimeMillis());
            Thread.sleep(5000);
            System.out.println("methodB end ThreadName=" + Thread.currentThread().getName() + " time= " + System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        finally {
            lock.unlock();
        }
    }

}

package ConditionTestMoreMethod;

/**
 * @author
 * @create 2020-11-19 15:05
 **/
public class ThreadA extends Thread {
    private MyService service;
    public  ThreadA(MyService service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.methodA();
    }
}

package ConditionTestMoreMethod;

/**
 * @author
 * @create 2020-11-19 15:07
 **/
public class ThreadAA extends Thread{
    private MyService service;
    public  ThreadAA(MyService service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.methodA();
    }
}


package ConditionTestMoreMethod;

/**
 * @author
 * @create 2020-11-19 15:07
 **/
public class ThreadB extends Thread {
    private MyService service;
    public  ThreadB(MyService service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.methodB();
    }
}


package ConditionTestMoreMethod;

/**
 * @author
 * @create 2020-11-19 15:07
 **/
public class ThreadBB extends Thread{
    private MyService service;
    public  ThreadBB(MyService service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.methodB();
    }
}

package ConditionTestMoreMethod;

/**
 * @author
 * @create 2020-11-19 15:09
 **/
public class Run {

    public static void main(String[] args) throws InterruptedException {
        MyService service = new MyService();
        ThreadA a  = new ThreadA(service);
        a.setName("A");
        a.start();
        ThreadA aa  = new ThreadA(service);
        aa.setName("AA");
        aa.start();
        Thread.sleep(100);
        ThreadB b = new ThreadB(service);
        b.setName("B");
        b.start();
        ThreadBB bb = new ThreadBB(service);
        bb.setName("BB");
        bb.start();

    }
}

在这里插入图片描述

1 调用 lock.lock()这个代码的线程持有了“”对象监视器“”,其他线程只能等待锁被释放时,再次争抢。
2 效果和使用synchronized关键字是一样的。线程之间还是顺序执行的。

使用condition 实现等待/通知

1 关键字 synchronized 与 wait() 和 notify() / notifyAll() 方法相结合可以实现等待/通知模式。
2 类ReentrantLock 结合 Condition 对象 可以实现同样的功能。
3 Lock对象可以创建多个Condition 对象监视器 实例,线程对象可以注册在指定的condition 中,从而有选择的进行某一类的线程通知。调度更加灵活。

区别

  • notify 、和notifyAll 方法进行通知的时候,被通知的线程却是由JVM 随机选择的。但是ReentrantLock 结合 condition 类是可以实现前面介绍过的“”选择性通知“”
  • synchronized 就相当于整个的Lock 对象中只有一个单一的Condition对象。所有的线程都注册在一个对象身上。notifyAll()方法调用的时候,会通知所有的waiting的线程。没有选择权,效率很低。
package UseConditionWaitNotifyError;

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

/**
 * @author
 * @create 2020-11-19 15:37
 **/
public class MyService {
    private Lock lock  = new ReentrantLock();
    private Condition condition = lock.newCondition();
    public void await() {
        try {
            condition.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

package UseConditionWaitNotifyError;

/**
 * @author
 * @create 2020-11-19 15:43
 **/
public class ThreadA extends Thread{
    private MyService service;

    public ThreadA(MyService service) {
        super();
        this.service= service;
    }

    @Override
    public void run() {
        service.await();
    }
}


package UseConditionWaitNotifyError;

/**
 * @author
 * @create 2020-11-19 15:44
 **/
public class Run {

    public static void main(String[] args) {
        MyService service = new MyService();
        ThreadA a = new ThreadA(service);
        a.start();
    }
}

在这里插入图片描述
报错异常信息是监视器出错,解决办法是必须在condition.await()方法调用之前调用lock.lock()代码获得同步监视器。

package UseConditionWaitNotifyOk;

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

/**
 * @author
 * @create 2020-11-19 15:50
 **/
public class MyService {
    private Lock lock  = new ReentrantLock();
    private Condition condition = lock.newCondition();
    public void waitMethod() {
        try {
            lock.lock();
            System.out.println("A");
            condition.await();
            System.out.println("B");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
            System.out.println("锁被释放了! ");
        }
    }

}

在这里插入图片描述
这里线程调用了 Condition 对象的await() 方法,是当前执行的任务的线程进入了等待,waiting 状态。

正确使用Condition 实现等待/通知

使用 Condition 类中的await方法实现 等待通知机制

Object 类中的wait() 方法相当于Condition 类中的 await()方法、
Object类中的wait(long timeout) 方法 相当于 Condition 中的 awat(long timeout,TimeUnit unit) 方法。

Object 类中的notify()方法相当于Condition类中的signal()方法。
Object 类中的notifyAll() 方法相当于Condition类中的signalAll() 方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值