ReferenceQueue引用队列——被

类的原注释,翻译过来是:

引用队列,在检测到适当的可达性更改后,垃圾收集器会将已注册的参考对象,附加到这些队列中。

  1. public class ReferenceQueue<T> {
  2. // ...
  3. // 1. 静态内容,
  4. static final ReferenceQueue<Object> NULL = new Null();
  5. static final ReferenceQueue<Object> ENQUEUED = new Null();
  6. private static class Null extends ReferenceQueue<Object> {
  7. boolean enqueue(Reference<?> r) {
  8. return false;
  9. }
  10. }
  11. // 当前对象的锁操作
  12. private static class Lock { };
  13. private final Lock lock = new Lock();
  14. // 链表标识
  15. private volatile Reference<? extends T> head;
  16. private long queueLength = 0;
  17. // 入队,仅被Reference操作
  18. boolean enqueue(Reference<? extends T> r) { /* Called only by Reference class */
  19. // 同步方法锁
  20. synchronized (lock) {
  21. // Check that since getting the lock this reference hasn't already been
  22. // enqueued (and even then removed)
  23. // 1. 拿到引用队列,如果支持
  24. ReferenceQueue<?> queue = r.queue;
  25. if ((queue == NULL) || (queue == ENQUEUED)) {
  26. return false;
  27. }
  28. assert queue == this;
  29. // Self-loop end, so if a FinalReference it remains inactive.
  30. r.next = (head == null) ? r : head;
  31. head = r;
  32. queueLength++;
  33. // Update r.queue *after* adding to list, to avoid race
  34. // with concurrent enqueued checks and fast-path poll().
  35. // Volatiles ensure ordering.
  36. r.queue = ENQUEUED;
  37. if (r instanceof FinalReference) {
  38. VM.addFinalRefCount(1);
  39. }
  40. lock.notifyAll();
  41. return true;
  42. }
  43. }
  44. private Reference<? extends T> reallyPoll() { /* Must hold lock */
  45. Reference<? extends T> r = head;
  46. if (r != null) {
  47. r.queue = NULL;
  48. // Update r.queue *before* removing from list, to avoid
  49. // race with concurrent enqueued checks and fast-path
  50. // poll(). Volatiles ensure ordering.
  51. @SuppressWarnings("unchecked")
  52. Reference<? extends T> rn = r.next;
  53. // Handle self-looped next as end of list designator.
  54. head = (rn == r) ? null : rn;
  55. // Self-loop next rather than setting to null, so if a
  56. // FinalReference it remains inactive.
  57. r.next = r;
  58. queueLength--;
  59. if (r instanceof FinalReference) {
  60. VM.addFinalRefCount(-1);
  61. }
  62. return r;
  63. }
  64. return null;
  65. }
  66. /**
  67. * Polls this queue to see if a reference object is available. If one is
  68. * available without further delay then it is removed from the queue and
  69. * returned. Otherwise this method immediately returns {@code null}.
  70. *
  71. * @return A reference object, if one was immediately available,
  72. * otherwise {@code null}
  73. */
  74. public Reference<? extends T> poll() {
  75. if (head == null)
  76. return null;
  77. synchronized (lock) {
  78. return reallyPoll();
  79. }
  80. }
  81. /**
  82. * Removes the next reference object in this queue, blocking until either
  83. * one becomes available or the given timeout period expires.
  84. *
  85. * <p> This method does not offer real-time guarantees: It schedules the
  86. * timeout as if by invoking the {@link Object#wait(long)} method.
  87. *
  88. * @param timeout If positive, block for up to {@code timeout}
  89. * milliseconds while waiting for a reference to be
  90. * added to this queue. If zero, block indefinitely.
  91. *
  92. * @return A reference object, if one was available within the specified
  93. * timeout period, otherwise {@code null}
  94. *
  95. * @throws IllegalArgumentException
  96. * If the value of the timeout argument is negative
  97. *
  98. * @throws InterruptedException
  99. * If the timeout wait is interrupted
  100. */
  101. public Reference<? extends T> remove(long timeout)
  102. throws IllegalArgumentException, InterruptedException
  103. {
  104. if (timeout < 0) {
  105. throw new IllegalArgumentException("Negative timeout value");
  106. }
  107. synchronized (lock) {
  108. Reference<? extends T> r = reallyPoll();
  109. if (r != null) return r;
  110. long start = (timeout == 0) ? 0 : System.nanoTime();
  111. for (;;) {
  112. lock.wait(timeout);
  113. r = reallyPoll();
  114. if (r != null) return r;
  115. if (timeout != 0) {
  116. long end = System.nanoTime();
  117. timeout -= (end - start) / 1000_000;
  118. if (timeout <= 0) return null;
  119. start = end;
  120. }
  121. }
  122. }
  123. }
  124. /**
  125. * Removes the next reference object in this queue, blocking until one
  126. * becomes available.
  127. *
  128. * @return A reference object, blocking until one becomes available
  129. * @throws InterruptedException If the wait is interrupted
  130. */
  131. public Reference<? extends T> remove() throws InterruptedException {
  132. return remove(0);
  133. }
  134. /**
  135. * Iterate queue and invoke given action with each Reference.
  136. * Suitable for diagnostic purposes.
  137. * WARNING: any use of this method should make sure to not
  138. * retain the referents of iterated references (in case of
  139. * FinalReference(s)) so that their life is not prolonged more
  140. * than necessary.
  141. */
  142. void forEach(Consumer<? super Reference<? extends T>> action) {
  143. for (Reference<? extends T> r = head; r != null;) {
  144. action.accept(r);
  145. @SuppressWarnings("unchecked")
  146. Reference<? extends T> rn = r.next;
  147. if (rn == r) {
  148. if (r.queue == ENQUEUED) {
  149. // still enqueued -> we reached end of chain
  150. r = null;
  151. } else {
  152. // already dequeued: r.queue == NULL; ->
  153. // restart from head when overtaken by queue poller(s)
  154. r = head;
  155. }
  156. } else {
  157. // next in chain
  158. r = rn;
  159. }
  160. }
  161. }
  162. }