6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
authormartin
Mon, 20 Apr 2009 21:57:01 -0700
changeset 2632 9779b9cbae42
parent 2631 29398881792c
child 2634 3b7f52bf2284
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id Summary: Make j.u.l. thread id a copy of Thread's id, for small values of thread id. Reviewed-by: alanb
jdk/src/share/classes/java/util/logging/LogRecord.java
jdk/test/java/util/logging/LoggerSubclass.java
--- a/jdk/src/share/classes/java/util/logging/LogRecord.java	Mon Apr 20 21:53:38 2009 -0700
+++ b/jdk/src/share/classes/java/util/logging/LogRecord.java	Mon Apr 20 21:57:01 2009 -0700
@@ -25,6 +25,8 @@
 
 package java.util.logging;
 import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
 import java.io.*;
 
 /**
@@ -64,9 +66,24 @@
  */
 
 public class LogRecord implements java.io.Serializable {
-    private static long globalSequenceNumber;
-    private static int nextThreadId=10;
-    private static ThreadLocal<Integer> threadIds = new ThreadLocal<Integer>();
+    private static final AtomicLong globalSequenceNumber
+        = new AtomicLong(0);
+
+    /**
+     * The default value of threadID will be the current thread's
+     * thread id, for ease of correlation, unless it is greater than
+     * MIN_SEQUENTIAL_THREAD_ID, in which case we try harder to keep
+     * our promise to keep threadIDs unique by avoiding collisions due
+     * to 32-bit wraparound.  Unfortunately, LogRecord.getThreadID()
+     * returns int, while Thread.getId() returns long.
+     */
+    private static final int MIN_SEQUENTIAL_THREAD_ID = Integer.MAX_VALUE / 2;
+
+    private static final AtomicInteger nextThreadId
+        = new AtomicInteger(MIN_SEQUENTIAL_THREAD_ID);
+
+    private static final ThreadLocal<Integer> threadIds
+        = new ThreadLocal<Integer>();
 
     /**
      * @serial Logging message level
@@ -123,6 +140,23 @@
     private transient ResourceBundle resourceBundle;
 
     /**
+     * Returns the default value for a new LogRecord's threadID.
+     */
+    private int defaultThreadID() {
+        long tid = Thread.currentThread().getId();
+        if (tid < MIN_SEQUENTIAL_THREAD_ID) {
+            return (int) tid;
+        } else {
+            Integer id = threadIds.get();
+            if (id == null) {
+                id = nextThreadId.getAndIncrement();
+                threadIds.set(id);
+            }
+            return id;
+        }
+    }
+
+    /**
      * Construct a LogRecord with the given level and message values.
      * <p>
      * The sequence property will be initialized with a new unique value.
@@ -144,15 +178,8 @@
         this.level = level;
         message = msg;
         // Assign a thread ID and a unique sequence number.
-        synchronized (LogRecord.class) {
-            sequenceNumber = globalSequenceNumber++;
-            Integer id = threadIds.get();
-            if (id == null) {
-                id = new Integer(nextThreadId++);
-                threadIds.set(id);
-            }
-            threadID = id.intValue();
-        }
+        sequenceNumber = globalSequenceNumber.getAndIncrement();
+        threadID = defaultThreadID();
         millis = System.currentTimeMillis();
         needToInferCaller = true;
    }
--- a/jdk/test/java/util/logging/LoggerSubclass.java	Mon Apr 20 21:53:38 2009 -0700
+++ b/jdk/test/java/util/logging/LoggerSubclass.java	Mon Apr 20 21:57:01 2009 -0700
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 6830220
+ * @bug 6830220 6278014
  * @summary Test Logger subclasses
  */
 
@@ -68,6 +68,8 @@
                           l.getSequenceNumber());
                     equal(lastThreadID.get(),
                           l.getThreadID());
+                    equal((int) Thread.currentThread().getId(),
+                          l.getThreadID());
                 }
                 lastSequenceNumber.set(l.getSequenceNumber());
                 lastThreadID.set(l.getThreadID());