Reduce synchronization overhead in HashedWheelTimer.start/stop()

This commit is contained in:
Trustin Lee 2012-10-16 13:36:36 -07:00
parent e7c6c88063
commit b291d85757

View File

@ -30,7 +30,6 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@ -86,7 +85,7 @@ public class HashedWheelTimer implements Timer {
private final Worker worker = new Worker();
final Thread workerThread;
final AtomicBoolean shutdown = new AtomicBoolean();
final AtomicInteger workerState = new AtomicInteger(); // 0 - init, 1 - started, 2 - shut down
private final long roundDuration;
final long tickDuration;
@ -241,18 +240,24 @@ public class HashedWheelTimer implements Timer {
* @throws IllegalStateException if this timer has been
* {@linkplain #stop() stopped} already
*/
public synchronized void start() {
if (shutdown.get()) {
public void start() {
switch (workerState.get()) {
case 0:
if (workerState.compareAndSet(0, 1)) {
workerThread.start();
}
break;
case 1:
break;
case 2:
throw new IllegalStateException("cannot be started once stopped");
}
if (!workerThread.isAlive()) {
workerThread.start();
default:
throw new Error();
}
}
@Override
public synchronized Set<Timeout> stop() {
public Set<Timeout> stop() {
if (Thread.currentThread() == workerThread) {
throw new IllegalStateException(
HashedWheelTimer.class.getSimpleName() +
@ -260,7 +265,9 @@ public class HashedWheelTimer implements Timer {
TimerTask.class.getSimpleName());
}
if (!shutdown.compareAndSet(false, true)) {
if (!workerState.compareAndSet(1, 2)) {
// workerState can be 0 or 2 at this moment - let it always be 2.
workerState.set(2);
return Collections.emptySet();
}
@ -300,9 +307,7 @@ public class HashedWheelTimer implements Timer {
throw new NullPointerException("unit");
}
if (!workerThread.isAlive()) {
start();
}
start();
delay = unit.toMillis(delay);
HashedWheelTimeout timeout = new HashedWheelTimeout(task, currentTime + delay);
@ -355,7 +360,7 @@ public class HashedWheelTimer implements Timer {
startTime = System.currentTimeMillis();
tick = 1;
while (!shutdown.get()) {
while (workerState.get() == 1) {
final long deadline = waitForNextTick();
if (deadline > 0) {
fetchExpiredTimeouts(expiredTimeouts, deadline);
@ -448,7 +453,7 @@ public class HashedWheelTimer implements Timer {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
if (shutdown.get()) {
if (workerState.get() != 1) {
return -1;
}
}