4. ConcurrentLinkedQueue 비차단 무제한 연결 목록 큐
ConcurrentLinkedQueue는 스레드로부터 안전한 큐 기반입니다. 연결된 목록의 구조는 무한한 대기열로 구현됩니다. 이론적으로 대기열의 길이는 무한히 확장될 수 있습니다.
다른 대기열과 마찬가지로 ConcurrentLinkedQueue도 FIFO(선입선출) 대기열 추가 규칙을 사용하여 요소를 정렬합니다. (추천 연구: java 인터뷰 질문)
큐에 요소를 추가하면 새로 삽입된 요소가 큐의 끝에 삽입됩니다. 요소는 대기열의 헤드에서 가져옵니다.
ConcurrentLinkedQueue는 연결 목록 구조이기 때문에 대기열에 들어갈 때 삽입된 요소는 연결 목록을 형성하기 위해 뒤로 확장되며 대기열에서 빼면 연결 목록의 첫 번째 요소부터 시작하여 증가합니다. 시퀀스;
ConcurrentLinkedQueue를 사용할 때 대기열이 비어 있는지 여부를 판단하는 경우 size()==0을 사용하지 않는 것을 기억하세요. passed 전체 연결리스트를 순회하는 방식으로 구현되는데, queue에 요소가 많을 경우 size() 메소드는 성능과 시간을 많이 소모하므로 단순히 queue가 비어 있는지 판단하기 위해 isEmpty()를 사용하면 됩니다.
public class ConcurrentLinkedQueueTest {<br/> public static int threadCount = 10;<br/> public static ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<String>();<br/> static class Offer implements Runnable {<br/> public void run() {<br/> //不建议使用 queue.size()==0,影响效率。可以使用!queue.isEmpty()<br/> if (queue.size() == 0) {<br/> String ele = new Random().nextInt(Integer.MAX_VALUE) + "";<br/> queue.offer(ele);<br/> System.out.println("入队元素为" + ele);<br/> }<br/> }<br/> }<br/> static class Poll implements Runnable {<br/> public void run() {<br/> if (!queue.isEmpty()) {<br/> String ele = queue.poll();<br/> System.out.println("出队元素为" + ele);<br/> }<br/> }<br/> }<br/> public static void main(String[] agrs) {<br/> ExecutorService executorService = Executors.newFixedThreadPool(4);<br/> for (int x = 0; x < threadCount; x++) {<br/> executorService.submit(new Offer());<br/> executorService.submit(new Poll());<br/> }<br/> executorService.shutdown();<br/> }<br/>}<br/>
출력:
入队元素为313732926<br/>出队元素为313732926<br/>入队元素为812655435<br/>出队元素为812655435<br/>入队元素为1893079357<br/>出队元素为1893079357<br/>入队元素为1137820958<br/>出队元素为1137820958<br/>入队元素为1965962048<br/>出队元素为1965962048<br/>出队元素为685567162<br/>入队元素为685567162<br/>出队元素为1441081163<br/>入队元素为1441081163<br/>出队元素为1627184732<br/>入队元素为1627184732<br/>
ConcurrentLinkedQuere 클래스 다이어그램
# 🎜 🎜#
public ConcurrentLinkedQueue(){<br/> head=tail=new Node<E>(null);<br/>}<br/>위 코드가 초기화되면 항목이 NULL인 빈 노드가 연결리스트의 선두 노드와 꼬리 노드로 구성됩니다. Offer 동작 Offer 동작은 연결리스트 끝에 요소를 추가하는 것인데,
구현 원리를 살펴보겠습니다.
public boolean offer(E e) {<br/> //e 为 null 则抛出空指针异常<br/> checkNotNull(e);<br/> //构造 Node 节点构造函数内部调用 unsafe.putObject,后面统一讲<br/> final Node<E> newNode = new Node<E>(e);<br/> //从尾节点插入<br/> for (Node<E> t = tail, p = t; ; ) {<br/> Node<E> q = p.next;<br/> //如果 q=null 说明 p 是尾节点则插入<br/> if (q == null) {<br/> //cas 插入(1)<br/> if (p.casNext(null, newNode)) {<br/> //cas 成功说明新增节点已经被放入链表,然后设置当前尾节点(包含 head,1,3,5.。。个节点为尾节点)<br/> if (p != t)// hop two nodes at a time<br/> casTail(t, newNode); // Failure is OK. return true;<br/> }<br/> // Lost CAS race to another thread; re-read next<br/> } else if (p == q)//(2)<br/> //多线程操作时候,由于 poll 时候会把老的 head 变为自引用,然后 head 的 next 变为新 head,所以这里需要<br/> //重新找新的 head,因为新的 head 后面的节点才是激活的节点<br/> p = (t != (t = tail)) ? t : head;<br/> else<br/> // 寻找尾节点(3)<br/> p = (p != t && t != (t = tail)) ? t : q;<br/> }<br/>}<br/>생성자에서 우리는 시작 부분에 null 항목이 있는 sentinel 노드가 있고 헤드와 테일 모두 이 노드를 가리킨다는 것을 알고 있습니다.
위 내용은 Java 멀티스레딩 및 동시성 인터뷰 질문(질문 4, 답변 포함)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!