当前位置 主页 > 网站技术 > 代码类 >

    java多线程加锁以及Condition类的使用实例解析

    栏目:代码类 时间:2019-11-27 12:08

    这篇文章主要介绍了java多线程加锁以及Condition类的使用实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    看了网上非常多的运行代码,很多都是重复的再说一件事,可能对于java老鸟来说,理解java的多线程是非常容易的事情,但是对于我这样的菜鸟来说,这个实在有点难,可能是我太菜了,网上重复的陈述对于我理解这个问题一点帮助都没有.所以这里我写下我对于这个问题的理解,目的是为了防止我忘记.

    还是从代码实例开始讲起:

    代码

    import java.util.Arrays;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.ReentrantLock;
    import java.util.function.Predicate;
    
    public class Main {
      public static void main(String[] args) throws InterruptedException {
        MyBlockingQueue<Integer> queue = new MyBlockingQueue<>(1);
        for (int i = 0; i < 10; i++) {
          int data = i;
          new Thread(() -> {
            try {
              queue.enqueue(data);
            } catch (InterruptedException e) {
              e.printStackTrace();
            }
          }).start();
        }
        System.out.println("1111111");
        for(int i=0;i<10;i++){
          new Thread(() -> {
            try {
              queue.dequeue();
            }catch (InterruptedException e){
              e.printStackTrace();
            }
          }).start();
        }
      }
      public static class MyBlockingQueue<E> {
        int size;//阻塞队列最大容量
        ReentrantLock lock = new ReentrantLock(true);
        LinkedList<E> list=new LinkedList<>();//队列底层实现
        Condition notFull = lock.newCondition();//队列满时的等待条件
        Condition notEmpty = lock.newCondition();//队列空时的等待条件
        public MyBlockingQueue(int size) {
          this.size = size;
        }
        public void enqueue(E e) throws InterruptedException {
          lock.lock();
          try {
            while(list.size() ==size)//队列已满,在notFull条件上等待
              notFull.await();
    
            list.add(e);//入队:加入链表末尾
            System.out.println("入队:" +e);
            notEmpty.signal(); //通知在notEmpty条件上等待的线程
          } finally {
            lock.unlock();
          }
        }
        public E dequeue() throws InterruptedException {
          E e;
          lock.lock();
          try {
            while(list.size() == 0)
              notEmpty.await();
            e = list.removeFirst();//出队:移除链表首元素
            System.out.println("出队:"+e);
            notFull.signal();//通知在notFull条件上等待的线程
            return e;
          } finally {
            lock.unlock();
          }
        }
      }
    }

    主函数启动了20个线程,前10个是入队的后10个是出队的,我们可以看啊可能输出结果,

    new Thread(() -> {
    try {
    queue.enqueue(data);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }).start(); 

    注意到线程实现,这个是lambda表达式实现Runable接口.

    入队:0
    出队:0
    入队:2
    出队:2
    入队:1
    出队:1
    入队:3
    出队:3
    入队:4
    出队:4
    入队:5
    出队:5
    入队:6
    出队:6
    入队:7
    出队:7
    入队:8
    出队:8
    入队:9
    出队:9

    可以看到1111111在第一个出队之前,队列容量为1,也就是说头10个入队进程只有第一个成功了,其他均被阻塞.