干货来袭:图解Java多线程(十一)

开课吧开课吧锤锤2021-03-17 09:37

    Java编程语言是一种简单、面向对象、分布式、解释型、健壮安全、与系统无关、可移植、高性能、多线程和动态的语言。如今Java已经广泛应用于各个领域的编程开发。

Java

    ReentrantLock

    可重入锁:一个线程获取到对象的锁后,执行方法内部在需要获取锁的时候是可以获取到的。如以下代码

    privatestaticfinalReentrantLockLOCK=newReentrantLock();

    privatestaticvoidm(){

    LOCK.lock();

    try{

    log.info("begin");

    //调用m1()

    m1();

    }finally{

    //注意锁的释放

    LOCK.unlock();

    }

    }

    publicstaticvoidm1(){

    LOCK.lock();

    try{

    log.info("m1");

    m2();

    }finally{

    //注意锁的释放

    LOCK.unlock();

    }

    }

    synchronized也是可重入锁,ReentrantLock有以下优点

    支持获取锁的超时时间

    获取锁时可被打断

    可设为公平锁

    可以有不同的条件变量,即有多个waitSet,可以指定唤醒

    api

    //默认非公平锁,参数传true表示未公平锁

    ReentrantLocklock=newReentrantLock(false);

    //尝试获取锁

    lock()

    //释放锁应放在finally块中必须执行到

    unlock()

    try{

    //获取锁时可被打断,阻塞中的线程可被打断

    LOCK.lockInterruptibly();

    }catch(InterruptedExceptione){

    return;

    }

    //尝试获取锁获取不到就返回false

    LOCK.tryLock()

    //支持超时时间一段时间没获取到就返回false

    tryLock(longtimeout,TimeUnitunit)

    //指定条件变量休息室一个锁可以创建多个休息室

    ConditionwaitSet=ROOM.newCondition();

    //释放锁进入waitSet等待释放后其他线程可以抢锁

    yanWaitSet.await()

    //唤醒具体休息室的线程唤醒后重写竞争锁

    yanWaitSet.signal()

    实例:一个线程输出a,一个线程输出b,一个线程输出c,abc按照顺序输出,连续输出5次

    这个考的就是线程的通信,利用wait()/notify()和控制变量可以实现,此处使用ReentrantLock即可实现该功能。

    publicstaticvoidmain(String[]args){

    AwaitSignalawaitSignal=newAwaitSignal(5);

    //构建三个条件变量

    Conditiona=awaitSignal.newCondition();

    Conditionb=awaitSignal.newCondition();

    Conditionc=awaitSignal.newCondition();

    //开启三个线程

    newThread(()->{

    awaitSignal.print("a",a,b);

    }).start();

    newThread(()->{

    awaitSignal.print("b",b,c);

    }).start();

    newThread(()->{

    awaitSignal.print("c",c,a);

    }).start();

    try{

    Thread.sleep(1000);

    }catch(InterruptedExceptione){

    e.printStackTrace();

    }

    awaitSignal.lock();

    try{

    //先唤醒a

    a.signal();

    }finally{

    awaitSignal.unlock();

    }

    }

    }

    classAwaitSignalextendsReentrantLock{

    //循环次数

    privateintloopNumber;

    publicAwaitSignal(intloopNumber){

    this.loopNumber=loopNumber;

    }

    /**

    *@paramprint输出的字符

    *@paramcurrent当前条件变量

    *@paramnext下一个条件变量

    */

    publicvoidprint(Stringprint,Conditioncurrent,Conditionnext){

    for(inti=0;i<loopNumber;i++){

    lock();

    try{

    try{

    //获取锁之后等待

    current.await();

    System.out.print(print);

    }catch(InterruptedExceptione){

    }

    next.signal();

    }finally{

    unlock();

    }

    }

    }

    以上内容由开课吧老师猿小布提供,更多Java教程尽在开课吧广场Java教程频道。

有用
分享