Reduce synchronization overhead in HashedWheelTimer.start/stop()
This commit is contained in:
parent
e7c6c88063
commit
b291d85757
@ -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;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user