• Condition条件队列


    synchronized

            结合Object上的wait和notify方法可以实现线程间的等待通知机制。

    ReentrantLock

            1:结合Condition接口同样可以实现这个功能。而且相比前 者使用起来更清晰也更简单。

            2:ReentrantLock可以创建Condition对象,供调用者添加不同的条件队列,实现更灵活多样化的等待机制

    Condition与Object的wait/notify区别

            1.Condition能够支持不响应中断,而通过使用Object方式不支持

            2.Condition能够支持多个等待队列(new 多个Condition对象),而Object方式只能支持一个

            3.Condition能够支持超时时间的设置(超时自动唤醒),而Object不支持

    Condition的await()等待/signal()唤醒

    1. package com.lock;
    2. import org.apache.log4j.Logger;
    3. import java.util.concurrent.TimeUnit;
    4. import java.util.concurrent.locks.Condition;
    5. import java.util.concurrent.locks.ReentrantLock;
    6. public class AwaitTest1 {
    7. static ReentrantLock lock = new ReentrantLock();
    8. static Condition condition = lock.newCondition();
    9. static Logger log = Logger.getLogger(AwaitTest1.class);
    10. public static void main(String[] args) throws InterruptedException {
    11. new Thread("t1"){
    12. public void run() {
    13. try {
    14. lock.lock();
    15. log.debug(Thread.currentThread().getName()+"因为某些条件无法满足,进入等待");
    16. condition.await(); //进入等待
    17. log.debug(Thread.currentThread().getName()+"条件满足了被唤醒,开始工作");
    18. } catch (Exception e) {
    19. e.printStackTrace();
    20. } finally {
    21. lock.unlock();
    22. }
    23. }
    24. }.start();
    25. TimeUnit.SECONDS.sleep(4);
    26. //main线程负责唤醒t1
    27. lock.lock();
    28. condition.signal();//唤醒
    29. lock.unlock();
    30. }
    31. }
    32. /**
    33. * 此时的结果4秒后,主线程将t1线程唤醒,t1线程就继续执行后面的逻辑啦,打印了开始工作
    34. */

    进入等待可被打断 

    1. package com.lock;
    2. import org.apache.log4j.Logger;
    3. import java.util.concurrent.TimeUnit;
    4. import java.util.concurrent.locks.Condition;
    5. import java.util.concurrent.locks.ReentrantLock;
    6. public class AwaitTest2 {
    7. static ReentrantLock lock = new ReentrantLock();
    8. static Condition condition = lock.newCondition();
    9. static Logger log = Logger.getLogger(AwaitTest2.class);
    10. public static void main(String[] args) throws InterruptedException {
    11. Thread thread = new Thread("t1"){
    12. public void run() {
    13. try {
    14. lock.lock();
    15. log.debug(Thread.currentThread().getName()+"因为某些条件无法满足,进入等待");
    16. // condition.await(); //进入等待(t1线程被打断会抛出中断异常)
    17. condition.awaitUninterruptibly(); //进入等待(t1线程被打断不会抛出中断异常)
    18. log.debug(Thread.currentThread().getName()+"条件满足了被唤醒,开始工作");
    19. } catch (Exception e) {
    20. e.printStackTrace();
    21. } finally {
    22. lock.unlock();
    23. }
    24. }
    25. };
    26. thread.start();
    27. TimeUnit.SECONDS.sleep(4);
    28. thread.interrupt();//打断t1线程
    29. log.debug(Thread.currentThread().getName()+"打断t1线程");
    30. }
    31. }

    总结

    • 调用了await方法的线程会因为中断抛出异常
    • 调用了awaitUninterruptibly方法的线程不会因为中断抛出中断异常。

    awaitNanos(long nanosTimeout):超时等待

    上面的两个方法在不发生异常的情况下,会一直在等待被其他线程唤醒。接下来的三个方法,都是带有时间的等待,在一个时间范围内等待,超过这个时间范围,那么就会自己醒来。

    1. package com.condition;
    2. import org.apache.log4j.Logger;
    3. import java.util.concurrent.locks.Condition;
    4. import java.util.concurrent.locks.ReentrantLock;
    5. public class AwaitTest3 {
    6. static ReentrantLock lock = new ReentrantLock();
    7. static Condition condition = lock.newCondition();
    8. static Logger log = Logger.getLogger(AwaitTest3.class);
    9. public static void main(String[] args) throws InterruptedException {
    10. Thread thread = new Thread("t1"){
    11. public void run() {
    12. try {
    13. lock.lock();
    14. log.debug(Thread.currentThread().getName()+"因为某些条件无法满足,进入等待");
    15. condition.awaitNanos(5000000000l);//5秒,单位是纳秒
    16. log.debug(Thread.currentThread().getName()+"没人人唤醒我,超时了,自己醒来开始工作");
    17. } catch (Exception e) {
    18. e.printStackTrace();
    19. } finally {
    20. lock.unlock();
    21. }
    22. }
    23. };
    24. thread.start();
    25. }
    26. }

     超过截止时间等待后释放后自动唤醒

    ReentrantLock的超时等待

    ReentrantLock还给我们提供了获取锁超时等待的方法tryLock(),可以选择传入时间参数,表示指定等待的时间,无参则表示立即返回申请锁的boolean结果;

    设置让线程等待的时间,这个时间之后再获取锁

    1. package com.lock;
    2. import org.apache.log4j.Logger;
    3. import java.util.concurrent.TimeUnit;
    4. import java.util.concurrent.locks.ReentrantLock;
    5. public class LockTest5 {
    6. static ReentrantLock lock = new ReentrantLock();
    7. static Logger log = Logger.getLogger(LockTest5.class);
    8. public static void main(String[] args) throws InterruptedException {
    9. Thread t1 = new Thread(){
    10. public void run(){
    11. log.debug("t1启动---------");
    12. try {
    13. if (!lock.tryLock(2, TimeUnit.SECONDS)) {//尝试获取锁,如果获取失败则返回
    14. log.debug("t1拿不到锁,返回");
    15. return;
    16. }
    17. } catch (InterruptedException e) {
    18. e.printStackTrace();
    19. }
    20. log.debug("t1获得了锁");
    21. lock.unlock();
    22. log.debug("t1释放了锁");
    23. }};
    24. //主线程获得了锁
    25. lock.lock();
    26. log.debug("主线程获得了锁");
    27. t1.start();
    28. try {
    29. TimeUnit.SECONDS.sleep(3);
    30. log.debug("主线程休眠3秒钟");
    31. } finally {
    32. lock.unlock();
    33. log.debug("主线程释放了锁");
    34. }
    35. }
    36. }

  • 相关阅读:
    通过webkitAnimationEnd实现轮播动画
    测试报告编写
    Compose进度条
    sylixos 5.0.4 ecs
    买下房子却发现被查封了,怎么办?
    使用LibreOffice pdf批量转换为jpg
    数据库基本概念
    python网页爬虫xpath应用
    性能分析-java虚拟机性能监控
    java学习资料校内共享平台计算机毕业设计MyBatis+系统+LW文档+源码+调试部署
  • 原文地址:https://blog.csdn.net/asmall_cat/article/details/125550538