6623943: javax.swing.TimerQueue's thread occasionally fails to start
Reviewed-by: alexp
--- a/jdk/src/share/classes/javax/swing/JApplet.java Thu Jun 19 18:03:43 2008 +0400
+++ b/jdk/src/share/classes/javax/swing/JApplet.java Mon Jun 23 15:21:37 2008 -0400
@@ -131,10 +131,7 @@
// Check the timerQ and restart if necessary.
TimerQueue q = TimerQueue.sharedInstance();
if(q != null) {
- synchronized(q) {
- if(!q.running)
- q.start();
- }
+ q.startIfNeeded();
}
/* Workaround for bug 4155072. The shared double buffer image
--- a/jdk/src/share/classes/javax/swing/TimerQueue.java Thu Jun 19 18:03:43 2008 +0400
+++ b/jdk/src/share/classes/javax/swing/TimerQueue.java Mon Jun 23 15:21:37 2008 -0400
@@ -31,6 +31,7 @@
import java.util.*;
import java.util.concurrent.*;
+import java.util.concurrent.locks.*;
import java.util.concurrent.atomic.AtomicLong;
import sun.awt.AppContext;
@@ -52,7 +53,8 @@
new StringBuffer("TimerQueue.expiredTimersKey");
private final DelayQueue<DelayedTimer> queue;
- volatile boolean running;
+ private volatile boolean running;
+ private final Lock runningLock;
/* Lock object used in place of class object for synchronization.
* (4187686)
@@ -69,7 +71,8 @@
super();
queue = new DelayQueue<DelayedTimer>();
// Now start the TimerQueue thread.
- start();
+ runningLock = new ReentrantLock();
+ startIfNeeded();
}
@@ -87,33 +90,30 @@
}
- synchronized void start() {
- if (running) {
- throw new RuntimeException("Can't start a TimerQueue " +
- "that is already running");
- }
- else {
- final ThreadGroup threadGroup =
- AppContext.getAppContext().getThreadGroup();
- java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction() {
- public Object run() {
- Thread timerThread = new Thread(threadGroup, TimerQueue.this,
- "TimerQueue");
- timerThread.setDaemon(true);
- timerThread.setPriority(Thread.NORM_PRIORITY);
- timerThread.start();
- return null;
- }
- });
- running = true;
+ void startIfNeeded() {
+ if (! running) {
+ runningLock.lock();
+ try {
+ final ThreadGroup threadGroup =
+ AppContext.getAppContext().getThreadGroup();
+ java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction() {
+ public Object run() {
+ Thread timerThread = new Thread(threadGroup, TimerQueue.this,
+ "TimerQueue");
+ timerThread.setDaemon(true);
+ timerThread.setPriority(Thread.NORM_PRIORITY);
+ timerThread.start();
+ return null;
+ }
+ });
+ running = true;
+ } finally {
+ runningLock.unlock();
+ }
}
}
- synchronized void stop() {
- running = false;
- }
-
void addTimer(Timer timer, long delayMillis) {
timer.getLock().lock();
try {
@@ -164,6 +164,7 @@
public void run() {
+ runningLock.lock();
try {
while (running) {
try {
@@ -195,14 +196,14 @@
}
}
catch (ThreadDeath td) {
- synchronized (this) {
- running = false;
- // Mark all the timers we contain as not being queued.
- for (DelayedTimer delayedTimer : queue) {
- delayedTimer.getTimer().cancelEvent();
- }
- throw td;
+ // Mark all the timers we contain as not being queued.
+ for (DelayedTimer delayedTimer : queue) {
+ delayedTimer.getTimer().cancelEvent();
}
+ throw td;
+ } finally {
+ running = false;
+ runningLock.unlock();
}
}