java 集合 学习记录

1.map遍历

		Map map = new HashMap<>();
		map.put("*", "123");
		map.put("+", "456");
		map.put("-", "123");
		System.err.println(map.toString());
		//1.entrySet
		Iterator<Map.Entry<String, String>> iterator3 = map.entrySet().iterator();
		while(iterator3.hasNext()) {
			Entry<String, String> entry = iterator3.next();
			System.out.println("entrySet:"+entry.getKey()+":"+entry.getValue());
		}
		//2.keySet
		Iterator iterator4 = map.keySet().iterator();
		while(iterator4.hasNext()) 
			System.err.println("keySet:"+map.get(iterator4.next()));
		//3.values集合
		Collection values = map.values();
		for (Object object : values) 
			System.err.println("values集合:"+object);
		//4.lambda表达式
		map.forEach((key,value)->System.err.println("map.forEach:"+key+":"+value));
		//5.stream 流遍历
		map.entrySet().stream().forEach(item->{
			Entry<String, String> entry = (Map.Entry<String, String>)item;
			System.out.println("stream:"+entry.getKey()+":"+entry.getValue());
		});

2.Set 遍历

		Set set = new HashSet<>();
		set.add("111");set.add("222");set.add("333");set.add("444");
		//1.Iterator遍历
		Iterator iterator2 = set.iterator();
		while(iterator2.hasNext()) {
			System.out.println("set_iterator:"+iterator2.next());
		}
		//2.toArray遍历
		if(set.contains("444")) {
			Object[] array1 = set.toArray();
			for (Object object : array1) {
				System.out.println("set_toArray:"+object);
			}
		}
		//3.lambda表达式
		set.forEach(key->{System.out.println("set_forEach:"+key);});
		//4.stream 流遍历
		set.stream().forEach(key->System.out.println("set_stream_forEach:"+key));

3.Stack 栈

线程安全的集合 Vector、 Stack 、Hashtable、 ConcurrentHashMap

		/**
		 * 栈(Stack) 是一种 后进先出(LIFO:Last In First Out) 的数据结构
		 *   把元素压栈:push(E);
		 *   把栈顶的元素“弹出”:pop();
		 *   取栈顶元素但不弹出:peek()
		 */
		Stack stack = new Stack<>();
		stack.add("123");
		//把项压入堆栈顶部
		stack.push("456");
		stack.push("789");
		System.out.println("栈元素:"+stack);
		System.err.println("取栈顶元素,不移除:"+stack.peek());
		System.err.println("返回对象再堆栈中的位置,以1为基数:"+stack.search("123"));
		System.err.println("移除栈顶元素:"+stack.pop());
		System.err.println("剩余栈元素:"+stack);

4.队列

四种队列实现方式,使用的是 ReentrantLock 锁

		//队列1.ArrayBlockingQueue 是一种基于数组结构的有界阻塞队列,其构造函数需要使用int参数来指定大小,且所含的对象是以先入先出的顺序排序
		//继承了 AbstractQueue 实现 BlockingQueue(继承了Queue)
		ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue(10);
		//队列2.LinkedBlockingQueue 是一种基于链表结构的阻塞队列,其构造函数需要使用一个规定大小的参数,且所含的对象是以先入先出的顺序排序
		LinkedBlockingQueue linkedBlockingQueue = new LinkedBlockingQueue();//默认大小 0x7fffffff
		//队列3.PriorityBlockingQueue 是一种具有优先级的无限阻塞队列,其所含的对象是以对象的自然排序顺序或者是构造函数进行排序。
		PriorityBlockingQueue priorityBlockingQueue = new PriorityBlockingQueue();// 默认大小11
		//队列4.SynchronousQueue 是一种不存储元素的阻塞队列,操作SynchronousQueue时需要等到另一个线程调用移除操作,否则操作会处于阻塞状态
		SynchronousQueue synchronousQueue = new SynchronousQueue();
继承和实现

在这里插入图片描述

1.数组队列 ArrayBlockingQueue

(1).构造
	public ArrayBlockingQueue(int capacity) {
        this(capacity, false);
    }
    public ArrayBlockingQueue(int capacity, boolean fair) {
        if (capacity <= 0)
            throw new IllegalArgumentException();
        this.items = new Object[capacity];
        lock = new ReentrantLock(fair);
        notEmpty = lock.newCondition();
        notFull =  lock.newCondition();
    }
    public ArrayBlockingQueue(int capacity, boolean fair,
                              Collection<? extends E> c) {
        this(capacity, fair);

        final ReentrantLock lock = this.lock;
        lock.lock(); // Lock only for visibility, not mutual exclusion
        try {
            int i = 0;
            try {
                for (E e : c) {
                    checkNotNull(e);
                    items[i++] = e;
                }
            } catch (ArrayIndexOutOfBoundsException ex) {
                throw new IllegalArgumentException();
            }
            count = i;
            putIndex = (i == capacity) ? 0 : i;
        } finally {
            lock.unlock();
        }
    }
(2).添加
	public boolean add(E e) {
        return super.add(e);
    }
    public void put(E e) throws InterruptedException {
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == items.length)
                notFull.await();
            enqueue(e);
        } finally {
            lock.unlock();
        }
    }
    public boolean offer(E e) {
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            if (count == items.length)
                return false;
            else {
                enqueue(e);
                return true;
            }
        } finally {
            lock.unlock();
        }
    }
(3).取元素
 	public E poll() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return (count == 0) ? null : dequeue();
        } finally {
            lock.unlock();
        }
    }

    public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == 0)
                notEmpty.await();
            return dequeue();
        } finally {
            lock.unlock();
        }
    }
    public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == 0)
                notEmpty.await();
            return dequeue();
        } finally {
            lock.unlock();
        }
    }
    public E peek() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return itemAt(takeIndex); // null when queue is empty
        } finally {
            lock.unlock();
        }
    }
(4).简单添加和移除测试
		//队列1.ArrayBlockingQueue 是一种基于数组结构的有界阻塞队列,其构造函数需要使用int参数来指定大小,且所含的对象是以先入先出的顺序排序
		//继承了 AbstractQueue 实现 BlockingQueue(继承了Queue)
		ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue(10);
		arrayBlockingQueue.add("123");//队列添加元素
		arrayBlockingQueue.add("456");
		try {
		 	//put添加抛出的有异常 
			arrayBlockingQueue.put("789");
			System.out.println("队列元素:"+arrayBlockingQueue);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("取队列顶元素,不移除:"+arrayBlockingQueue.peek()+"	此时在队列:"+arrayBlockingQueue);
		System.out.println("取队列顶元素,并移除:"+arrayBlockingQueue.poll()+"	此时在队列:"+arrayBlockingQueue);
		System.out.println("取队列顶元素,并移除:"+arrayBlockingQueue.remove()+"	此时在队列:"+arrayBlockingQueue);
		try {
			System.out.println("取队列顶元素,并移除:"+arrayBlockingQueue.take()+"	此时在队列:"+arrayBlockingQueue);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

在这里插入图片描述

同样有各种遍历方式
在这里插入图片描述

2.链表队列 LinkedBlockingQueue

(1).构造
	@Native public static final int   MAX_VALUE = 0x7fffffff;
	public LinkedBlockingQueue() {
        this(Integer.MAX_VALUE);
    }
    public LinkedBlockingQueue(int capacity) {
        if (capacity <= 0) throw new IllegalArgumentException();
        this.capacity = capacity;
        last = head = new Node<E>(null);
    }
    public LinkedBlockingQueue(Collection<? extends E> c) {
        this(Integer.MAX_VALUE);
        final ReentrantLock putLock = this.putLock;
        putLock.lock(); // Never contended, but necessary for visibility
        try {
            int n = 0;
            for (E e : c) {
                if (e == null)
                    throw new NullPointerException();
                if (n == capacity)
                    throw new IllegalStateException("Queue full");
                enqueue(new Node<E>(e));
                ++n;
            }
            count.set(n);
        } finally {
            putLock.unlock();
        }
    }
(2). 添加
	public boolean add(E e) {
        if (offer(e))
            return true;
        else
            throw new IllegalStateException("Queue full");
    }
    public boolean offer(E e) {
        if (e == null) throw new NullPointerException();
        final AtomicInteger count = this.count;
        if (count.get() == capacity)
            return false;
        int c = -1;
        Node<E> node = new Node<E>(e);
        final ReentrantLock putLock = this.putLock;
        putLock.lock();
        try {
            if (count.get() < capacity) {
                enqueue(node);
                c = count.getAndIncrement();
                if (c + 1 < capacity)
                    notFull.signal();
            }
        } finally {
            putLock.unlock();
        }
        if (c == 0)
            signalNotEmpty();
        return c >= 0;
    }
     public void put(E e) throws InterruptedException {
        if (e == null) throw new NullPointerException();
        // Note: convention in all put/take/etc is to preset local var
        // holding count negative to indicate failure unless set.
        int c = -1;
        Node<E> node = new Node<E>(e);
        final ReentrantLock putLock = this.putLock;
        final AtomicInteger count = this.count;
        putLock.lockInterruptibly();
        try {
            while (count.get() == capacity) {
                notFull.await();
            }
            enqueue(node);
            c = count.getAndIncrement();
            if (c + 1 < capacity)
                notFull.signal();
        } finally {
            putLock.unlock();
        }
        if (c == 0)
            signalNotEmpty();
    }
(3).取元素
	public E remove() {
        E x = poll();
        if (x != null)
            return x;
        else
            throw new NoSuchElementException();
    }
	public E take() throws InterruptedException {
        E x;
        int c = -1;
        final AtomicInteger count = this.count;
        final ReentrantLock takeLock = this.takeLock;
        takeLock.lockInterruptibly();
        try {
            while (count.get() == 0) {
                notEmpty.await();
            }
            x = dequeue();
            c = count.getAndDecrement();
            if (c > 1)
                notEmpty.signal();
        } finally {
            takeLock.unlock();
        }
        if (c == capacity)
            signalNotFull();
        return x;
    }
    public E poll() {
        final AtomicInteger count = this.count;
        if (count.get() == 0)
            return null;
        E x = null;
        int c = -1;
        final ReentrantLock takeLock = this.takeLock;
        takeLock.lock();
        try {
            if (count.get() > 0) {
                x = dequeue();
                c = count.getAndDecrement();
                if (c > 1)
                    notEmpty.signal();
            }
        } finally {
            takeLock.unlock();
        }
        if (c == capacity)
            signalNotFull();
        return x;
    }

    public E peek() {
        if (count.get() == 0)
            return null;
        final ReentrantLock takeLock = this.takeLock;
        takeLock.lock();
        try {
            Node<E> first = head.next;
            if (first == null)
                return null;
            else
                return first.item;
        } finally {
            takeLock.unlock();
        }
    }
(4).简单测试
		//默认大小 0x7fffffff
		LinkedBlockingQueue linkedBlockingQueue = new LinkedBlockingQueue();
		linkedBlockingQueue.add("123");
		linkedBlockingQueue.offer("789");
		linkedBlockingQueue.offer("101");
		try {
			linkedBlockingQueue.put("456");
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
		
		System.err.println("此时队列:"+linkedBlockingQueue);
		System.err.println("取队列顶元素,不移除:"+linkedBlockingQueue.peek()+"此时队列:"+linkedBlockingQueue);
		System.err.println("取队列顶元素,并移除:"+linkedBlockingQueue.poll()+"此时队列:"+linkedBlockingQueue);
		System.err.println("取队列顶元素,并移除:"+linkedBlockingQueue.remove()+"此时队列:"+linkedBlockingQueue);
		try {
			System.err.println("取队列顶元素,并移除:"+linkedBlockingQueue.take()+"此时队列:"+linkedBlockingQueue);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

在这里插入图片描述

3.有优先级队列 priorityBlockingQueue

其所含的对象是以对象的自然排序顺序或者是构造函数进行排序,优先队列是按照堆排序原理设计的

(1).构造
	private static final int DEFAULT_INITIAL_CAPACITY = 11;
	public PriorityBlockingQueue() {
        this(DEFAULT_INITIAL_CAPACITY, null);
    }
    public PriorityBlockingQueue(int initialCapacity) {
        this(initialCapacity, null);
    }
    public PriorityBlockingQueue(int initialCapacity,
                                 Comparator<? super E> comparator) {
        if (initialCapacity < 1)
            throw new IllegalArgumentException();
        this.lock = new ReentrantLock();
        this.notEmpty = lock.newCondition();
        this.comparator = comparator;
        this.queue = new Object[initialCapacity];
    }
    public PriorityBlockingQueue(Collection<? extends E> c) {
        this.lock = new ReentrantLock();
        this.notEmpty = lock.newCondition();
        boolean heapify = true; // true if not known to be in heap order
        boolean screen = true;  // true if must screen for nulls
        if (c instanceof SortedSet<?>) {
            SortedSet<? extends E> ss = (SortedSet<? extends E>) c;
            this.comparator = (Comparator<? super E>) ss.comparator();
            heapify = false;
        }
        else if (c instanceof PriorityBlockingQueue<?>) {
            PriorityBlockingQueue<? extends E> pq =
                (PriorityBlockingQueue<? extends E>) c;
            this.comparator = (Comparator<? super E>) pq.comparator();
            screen = false;
            if (pq.getClass() == PriorityBlockingQueue.class) // exact match
                heapify = false;
        }
        Object[] a = c.toArray();
        int n = a.length;
        if (c.getClass() != java.util.ArrayList.class)
            a = Arrays.copyOf(a, n, Object[].class);
        if (screen && (n == 1 || this.comparator != null)) {
            for (int i = 0; i < n; ++i)
                if (a[i] == null)
                    throw new NullPointerException();
        }
        this.queue = a;
        this.size = n;
        if (heapify)
            heapify();
    }
(2).添加

所有往队列中加入元素的方法最后都会调用offer方法。

	public boolean add(E e) {
        return offer(e);
    }
    public void put(E e) {
        offer(e); // never need to block
    }
    public boolean offer(E e) {
        if (e == null)
            throw new NullPointerException();
        final ReentrantLock lock = this.lock;
        lock.lock();
        int n, cap;
        Object[] array;
        //扩容
        while ((n = size) >= (cap = (array = queue).length))
            tryGrow(array, cap);
        try {
            Comparator<? super E> cmp = comparator;
            if (cmp == null)
                siftUpComparable(n, e, array);
            else
                siftUpUsingComparator(n, e, array, cmp);
            size = n + 1;
            notEmpty.signal();
        } finally {
            lock.unlock();
        }
        return true;
    }

方法有三个功能,分别是:扩容,插入新元素和同步 参考链接

(3).取元素
	public E poll() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return dequeue();
        } finally {
            lock.unlock();
        }
    }
    public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        E result;
        try {
            while ( (result = dequeue()) == null)
                notEmpty.await();
        } finally {
            lock.unlock();
        }
        return result;
    }
    public E poll(long timeout, TimeUnit unit) throws InterruptedException {
        long nanos = unit.toNanos(timeout);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        E result;
        try {
            while ( (result = dequeue()) == null && nanos > 0)
                nanos = notEmpty.awaitNanos(nanos);
        } finally {
            lock.unlock();
        }
        return result;
    }
     public E peek() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return (size == 0) ? null : (E) queue[0];
        } finally {
            lock.unlock();
        }
    }
(4).简单测试
		// 默认大小11
		PriorityBlockingQueue priorityBlockingQueue = new PriorityBlockingQueue();
		priorityBlockingQueue.add("123");
		priorityBlockingQueue.put("456");
		priorityBlockingQueue.offer("789");
		priorityBlockingQueue.offer("101");
		System.err.println("此时队列:"+priorityBlockingQueue);
		System.err.println("取队列顶元素,不移除:"+priorityBlockingQueue.peek()+"此时队列:"+priorityBlockingQueue);
		System.err.println("取队列顶元素,并移除:"+priorityBlockingQueue.poll()+"此时队列:"+priorityBlockingQueue);
		System.err.println("取队列顶元素,并移除:"+priorityBlockingQueue.remove()+"此时队列:"+priorityBlockingQueue);
		try {
			System.err.println("取队列顶元素,并移除:"+priorityBlockingQueue.take()+"此时队列:"+priorityBlockingQueue);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

在这里插入图片描述

先不做过多学习

4.不存储元素队列 SynchronousQueue

SynchronousQueue 的整体设计比较抽象,在内部抽象出了两种算法实现,一种是先入先出的队列,一种是后入先出的堆栈,两种算法被两个内部类实现,而直接对外的 put,take 方法的实现就非常简单,都是直接调用两个内部类的 transfer 方法进行实现

  1. 队列不存储数据,所以没有大小,也无法迭代;
  2. 插入操作的返回必须等待另一个线程完成对应数据的删除操作,反之亦然;
  3. 队列由两种数据结构组成,分别是后入先出的堆栈和先入先出的队列,堆栈是非公平的,队列是公平的。
构造

默认fasle,TransferStack ,为true时 TransferQueue

	public SynchronousQueue() {
        this(false);
    }
    public SynchronousQueue(boolean fair) {
        transferer = fair ? new TransferQueue<E>() : new TransferStack<E>();
    }
添加 add

add直接添加元素会抛出异常

		SynchronousQueue synchronousQueue = new SynchronousQueue();
		try {
			synchronousQueue.add("123");
		} catch (Exception e) {
			//异常 java.lang.IllegalStateException: Queue full
			e.printStackTrace();
		}
		System.err.println(synchronousQueue.peek()); // null

	//源码
	 public boolean add(E e) {
        if (offer(e))
            return true;
        else
            throw new IllegalStateException("Queue full");
    }
添加 put
		try {
			synchronousQueue.put("123"); //进入线程阻塞
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

源码

	public void put(E e) throws InterruptedException {
        if (e == null) throw new NullPointerException();
        if (transferer.transfer(e, false, 0) == null) {
            Thread.interrupted();
            throw new InterruptedException();
        }
    }

更改写法,添加线程

	Thread thread = new Thread() {
			public void run() {
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				try {
					System.err.println("synchronousQueue:"+synchronousQueue.take());
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			};
		};
		thread.start();
		try {
			System.err.println("线程进入阻塞");
			synchronousQueue.put("123");//进入线程阻塞
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.err.println("线程解除阻塞");

在这里插入图片描述

入栈和出栈

入栈指的是使用 put 等方法,把数据放到堆栈池中,出栈指的使用 take 等方法,把数据从堆栈池中拿出来,操作的对象都是堆栈头,虽然两者的一个是从堆栈头拿数据,一个是放数据,但底层实现的方法却是同一个
在这里插入图片描述

static final class TransferStack< E > extends Transferer< E >
在这里插入图片描述
TransferStack 源码transfer

		@SuppressWarnings("unchecked")
        E transfer(E e, boolean timed, long nanos) {
            SNode s = null; // constructed/reused as needed
            int mode = (e == null) ? REQUEST : DATA;

            for (;;) {
                SNode h = head;
                if (h == null || h.mode == mode) {  // empty or same-mode
                    if (timed && nanos <= 0) {      // can't wait
                        if (h != null && h.isCancelled())
                            casHead(h, h.next);     // pop cancelled node
                        else
                            return null;
                    } else if (casHead(h, s = snode(s, e, h, mode))) {
                        SNode m = awaitFulfill(s, timed, nanos);
                        if (m == s) {               // wait was cancelled
                            clean(s);
                            return null;
                        }
                        if ((h = head) != null && h.next == s)
                            casHead(h, s.next);     // help s's fulfiller
                        return (E) ((mode == REQUEST) ? m.item : s.item);
                    }
                } else if (!isFulfilling(h.mode)) { // try to fulfill
                    if (h.isCancelled())            // already cancelled
                        casHead(h, h.next);         // pop and retry
                    else if (casHead(h, s=snode(s, e, h, FULFILLING|mode))) {
                        for (;;) { // loop until matched or waiters disappear
                            SNode m = s.next;       // m is s's match
                            if (m == null) {        // all waiters are gone
                                casHead(s, null);   // pop fulfill node
                                s = null;           // use new node next time
                                break;              // restart main loop
                            }
                            SNode mn = m.next;
                            if (m.tryMatch(s)) {
                                casHead(s, mn);     // pop both s and m
                                return (E) ((mode == REQUEST) ? m.item : s.item);
                            } else                  // lost match
                                s.casNext(m, mn);   // help unlink
                        }
                    }
                } else {                            // help a fulfiller
                    SNode m = h.next;               // m is h's match
                    if (m == null)                  // waiter is gone
                        casHead(h, null);           // pop fulfilling node
                    else {
                        SNode mn = m.next;
                        if (m.tryMatch(h))          // help match
                            casHead(h, mn);         // pop both h and m
                        else                        // lost match
                            h.casNext(m, mn);       // help unlink
                    }
                }
            }
        }
  1. 判断是 put 方法还是 take 方法;
  2. 判断栈头数据是否为空,如果为空或者栈头的操作和本次操作一致,是的话走 3,否则走 5;
  3. 判断操作有无设置超时时间,如果设置了超时时间并且已经超时,返回 null,否则走 4;
  4. 如果栈头为空,把当前操作设置成栈头,或者栈头不为空,但栈头的操作和本次操作相同,也把当前操作设置成栈头,并看看其它线程能否满足自己,不能满足则阻塞自己。比如当前操作是
    take,但队列中没有数据,则阻塞自己;
  5. 如果栈头已经是阻塞住的,需要别人唤醒的,判断当前操作能否唤醒栈头,可以唤醒走 6,否则走 4;
  6. 把自己当作一个节点,赋值到栈头的 match 属性上,并唤醒栈头节点;
  7. 栈头被唤醒后,拿到 match 属性,就是把自己唤醒的节点的信息,返回。

公平的队列主要使用的是 TransferQueue 内部类的 transfer 方法
在这里插入图片描述

		@SuppressWarnings("unchecked")
        E transfer(E e, boolean timed, long nanos) {
            QNode s = null; // constructed/reused as needed
            boolean isData = (e != null);

            for (;;) {
                QNode t = tail;
                QNode h = head;
                if (t == null || h == null)         // saw uninitialized value
                    continue;                       // spin

                if (h == t || t.isData == isData) { // empty or same-mode
                    QNode tn = t.next;
                    if (t != tail)                  // inconsistent read
                        continue;
                    if (tn != null) {               // lagging tail
                        advanceTail(t, tn);
                        continue;
                    }
                    if (timed && nanos <= 0)        // can't wait
                        return null;
                    if (s == null)
                        s = new QNode(e, isData);
                    if (!t.casNext(null, s))        // failed to link in
                        continue;

                    advanceTail(t, s);              // swing tail and wait
                    Object x = awaitFulfill(s, e, timed, nanos);
                    if (x == s) {                   // wait was cancelled
                        clean(t, s);
                        return null;
                    }

                    if (!s.isOffList()) {           // not already unlinked
                        advanceHead(t, s);          // unlink if head
                        if (x != null)              // and forget fields
                            s.item = s;
                        s.waiter = null;
                    }
                    return (x != null) ? (E)x : e;

                } else {                            // complementary-mode
                    QNode m = h.next;               // node to fulfill
                    if (t != tail || m == null || h != head)
                        continue;                   // inconsistent read

                    Object x = m.item;
                    if (isData == (x != null) ||    // m already fulfilled
                        x == m ||                   // m cancelled
                        !m.casItem(x, e)) {         // lost CAS
                        advanceHead(h, m);          // dequeue and retry
                        continue;
                    }

                    advanceHead(h, m);              // successfully fulfilled
                    LockSupport.unpark(m.waiter);
                    return (x != null) ? (E)x : e;
                }
            }
        }

源码比较复杂,我们需要搞清楚的是,线程被阻塞住后,当前线程是如何把自己的数据传给阻塞线程的。为了方便说明,我们假设线程 1 往队列中 take 数据 ,被阻塞住了,变成阻塞线程 A ,然后线程 2 开始往队列中 put 数据 B,大致的流程是这样的:

  1. 线程 1 从队列中拿数据,发现队列中没有数据,于是被阻塞,成为 A ;
  2. 线程 2 往队尾 put 数据,会从队尾往前找到第一个被阻塞的节点,假设此时能找到的就是节点 A,然后线程 B 把将 put的数据放到节点 A 的 item 属性里面,并唤醒线程 1;
  3. 线程 1 被唤醒后,就能从 A.item 里面拿到线程 2 put 的数据了,线程 1 成功返回。

从这个过程中,我们能看出公平主要体现在,每次 put 数据的时候,都 put 到队尾上,而每次拿数据时,并不是直接从堆头拿数据,而是从队尾往前寻找第一个被阻塞的线程,这样就会按照顺序释放被阻塞的线程

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值