EventBus 시리즈 "번 외" - "PendingPostQueue" 대열 의 실현 사상 을 진지 하 게 분석 합 니 다.
EventBus
대열 의 실현 사상 을 말씀 드 리 겠 습 니 다. 제 다른 글 주소, 환영 품 읽 기:EventBus 시리즈 "1" - 등록 및 로그아웃
EventBus 시리즈 "2" - Post 와 post Sticky 이벤트 의 발표 와 수신
EventBus 시리즈 "번 외" - "PendingPostQueue" 대열 의 실현 사상 을 진지 하 게 분석 합 니 다.
콘 셉 트
무엇이 대열 입 니까?
대기 열 은 FIFO, 꼬리 부분 추가, 머리 삭제 (선진 대기 열의 요소 가 먼저 대기 열 에서 나 오 는 것 을 지원 하 는 데이터 구조 입 니 다.
자바 의 상용 대기 열
자바 에서
BlockingQueue
인 터 페 이 스 를 제공 합 니 다. 이 인 터 페 이 스 를 실현 하여 대기 열 저장 을 실현 합 니 다. 우리 가 자주 사용 하 는 대기 열 은?ArrayBlockingQueue
내부 에서 하나의 배열 을 유지 하고 배열 요소 에 대한 추가 삭제 와 검 사 를 통 해 대열 이 요소 FIFO (선진 선 출) 에 대한 순 서 를 실현 했다. LinkedBlockingQueue
메모리 에서 노드 노드 노드 를 유지 하고 대기 열 에서 요소 FIFO (먼저 나 가기) 를 정렬 합 니 다. 우 리 는 먼저 사건 을 대열 에 넣 는 과정 을 회상 해 보 자.
threadMode = MAIN
을 예 로 들 자.private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
switch (subscription.subscriberMethod.threadMode) {
...
case MAIN:
if (isMainThread) {
//
invokeSubscriber(subscription, event);
} else {
//
mainThreadPoster.enqueue(subscription, event);
}
break;
...
}
진입
HandlerPoster.java
, 실행 enqueue
, 대기 열 에 Event
넣 기public void enqueue(Subscription subscription, Object event) {
// Event PendingPost
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
synchronized (this) {
//
queue.enqueue(pendingPost);
if (!handlerActive) {
handlerActive = true;
if (!sendMessage(obtainMessage())) {
throw new EventBusException("Could not send handler message");
}
}
}
}
PendingPost Queue 대기 열의 실현
PendingPostQueue
대열 의 실현 은 상기 두 대열 과 다르다. 그 내 부 는 유지 보수
도 없고 유지 보수 Node
도 없 으 며 유지 보수 List
도 없다. 그러면 어떻게 이 루어 졌 을 까? 답 은 메모리 포인터 이다.우 리 는 먼저 내부 유지 보수 의 변수 가 어떤 것 이 있 는 지 알 아 보 겠 습 니 다.
final class PendingPostQueue {
//
private PendingPost head;
//
private PendingPost tail;
}
소스 코드 를 통 해 우 리 는
PendingPostQueue
대열 의 머리 와 꼬리 부분 이 모두 PendingPost
유형 으로 포장 되 었 음 을 볼 수 있다. 우 리 는 PendingPost
류 의 실현 을 살 펴 보 자.final class PendingPost {
private final static List pendingPostPool = new ArrayList();
Object event;
Subscription subscription;
// , PendingPost
PendingPost next;
private PendingPost(Object event, Subscription subscription) {
this.event = event;
this.subscription = subscription;
}
//@ : Event , 。
// Event PendingPost
static PendingPost obtainPendingPost(Subscription subscription, Object event) {
synchronized (pendingPostPool) {
int size = pendingPostPool.size();
// pendingPostPool
if (size > 0) {
//
PendingPost pendingPost = pendingPostPool.remove(size - 1);
//
pendingPost.event = event;
pendingPost.subscription = subscription;
pendingPost.next = null;
// PendingPost
return pendingPost;
}
}
//new PendingPost
return new PendingPost(event, subscription);
}
// pendingPost , 10000
static void releasePendingPost(PendingPost pendingPost) {
pendingPost.event = null;
pendingPost.subscription = null;
pendingPost.next = null;
synchronized (pendingPostPool) {
// Don't let the pool grow indefinitely
if (pendingPostPool.size() < 10000) {
pendingPostPool.add(pendingPost);
}
}
}
}
우 리 는 지식 프로 세 스 를 깔 기 전에 전체 이벤트 이 벤트 를
PendingPost
, 즉 실행 obtainPendingPost(Subscription subscription, Object event)
함수 로 봉 하 는 것 을 볼 수 있다.PendingPost Queue. java 로 돌아 가서 그 가 어떻게 창고 에 들 어가 고 창고 에서 나 오 는 지 봅 시다.
메모리 포인터 로 다음 요소 의 메모리 위 치 를 가리 키 며 요소 값 을 가 져 오 는 방법 을 봅 시다.
입고 절차
final class PendingPostQueue {
private PendingPost head;
private PendingPost tail;
synchronized void enqueue(PendingPost pendingPost) {
// pendingPost
if (pendingPost == null) {
throw new NullPointerException("null cannot be enqueued");
}
// ,
if (tail != null) {
tail.next = pendingPost; // tail next
tail = pendingPost; // tail
} else if (head == null) { // , ,
head = tail = pendingPost; //
} else {
throw new IllegalStateException("Head present, but no tail");
}
notifyAll();
}
}
tail.next = B
요소 B 를 A A.next
속성 치 에 부여 한 것 과 같 습 니 다. 이때 head.next
의 값 도 B 와 같 습 니 다. 이 어 우리 가 tail 에 새로운 값 B 를 부여 하면 이때 A.next
와 head.next
는 tail 과 같 습 니 다. tail
마지막 값 을 영원히 저장 합 니 다. head.next
계속 옮 겨 다 니 면 스 택 에 있 는 모든 값 을 저장 할 수 있 습 니 다. FIFO (선진 선 출) 정렬 원칙 출고 절차
final class PendingPostQueue {
private PendingPost head;
private PendingPost tail;
//
synchronized PendingPost poll() {
PendingPost pendingPost = head; //
if (head != null) { // head ,
head = head.next; // , head
if (head == null) { // ,
tail = null; // Null
}
}
return pendingPost; // pendingPost
}
// ,
synchronized PendingPost poll(int maxMillisToWait) throws InterruptedException {
if (head == null) {
wait(maxMillisToWait); //
}
return poll();
}
}
첫 번 째 실행
poll
은 머리의 pendingPost 요 소 를 가 져 온 다음 에 head
값 이 비어 있 는 지 판단 합 니 다. Null 이 아니라면 head.next
값 을 다음 실행 poll
의 head
값 으로 가 져 옵 니 다. 한 번 에 유추 head.next
가 Null
일 때 까지 다음 요소 가 없다 는 것 을 설명 하고 스 택 밑 에 있 습 니 다. tail
을 Null
설치 하고 끝 냅 니 다.단순 실례
편리 하 게 이해 하기 위해 저 는
EventBus
의 구조 에 따라 데모 샘플 을 만 들 었 습 니 다. 여러분 께 참고 하 시기 바 랍 니 다.Entry.java
public class Entry {
private String flag;
Entry next;
public Entry(String flag) {
this.flag = flag;
}
public static Entry createEntry(String flag) {
return new Entry(flag);
}
}
EntryControl.java
public class EntryControl {
private Entry head;
private Entry tail;
synchronized void enqueue(Entry entry) {
if (tail != null) {
tail.next = entry;
tail = entry;
} else if (head == null) {
head = tail = entry;
} else {
throw new IllegalStateException("Head present, but no tail");
}
System.out.println("Head HashCode:" + head.hashCode());
System.out.println("Tail HashCode:" + tail.hashCode());
notifyAll();
}
synchronized Entry poll() {
Entry entry = head;
if (head != null) {
head = head.next;
if (head == null) {
tail = null;
}
System.out.println("Current Head HashCode:" + entry.hashCode());
}
return entry;
}
}
Test. java 실행 프로그램
public class Test {
public static void main(String[] args) {
EntryControl entryControl = new EntryControl();
for (int index = 0; index < 5; index++) {
Entry entry = Entry.createEntry(" " + index);
entryControl.enqueue(entry);
}
System.out.println(" ===========================");
while (true) {
Entry pendingPost = entryControl.poll();
if (pendingPost == null) {
return;
}
// System.out.println().e(TAG," " + pendingPost.subscription + "," + pendingPost.event);
}
}
}
실행 결과
Head HashCode:356573597
Tail HashCode:356573597
Head HashCode:356573597
Tail HashCode:1735600054
Head HashCode:356573597
Tail HashCode:21685669
Head HashCode:356573597
Tail HashCode:2133927002
Head HashCode:356573597
Tail HashCode:1836019240
===========================
Current Head HashCode:356573597
Current Head HashCode:1735600054
Current Head HashCode:21685669
Current Head HashCode:2133927002
Current Head HashCode:1836019240
이렇게 하면 분명 해진 다.
This ALL! Thanks EveryBody!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.