Java 定时器优化:使用 Optional、Lambda 表达式、ConcurrentHashMap 和 优化 tryCancel 方法
Java 定时器优化
本文将介绍如何使用 Java 8 的 Optional 类、Lambda 表达式、ConcurrentHashMap 和 优化 tryCancel 方法来优化 Java 定时器代码,使其更加简洁、安全且高效。
代码优化
以下是优化后的代码:javaimport com.taobao.hsf.NamedThreadFactory;import com.taobao.powermsg3.sdk.localserver.PmLocalServerSDKConfig;import io.netty.util.HashedWheelTimer;import io.netty.util.Timeout;import io.netty.util.TimerTask;import io.vertx.core.Context;import lombok.extern.slf4j.Slf4j;import org.apache.commons.collections4.CollectionUtils;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;import javax.annotation.PreDestroy;import java.time.Duration;import java.util.Objects;import java.util.Set;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.TimeUnit;import java.util.concurrent.atomic.AtomicLong;
@Component@Slf4jpublic class Scheduler { private final HashedWheelTimer hashedWheelTimer;
private final AtomicLong timerIdGen = new AtomicLong();
private final ConcurrentHashMap<Long, Timeout> timerId2Timeout = new ConcurrentHashMap<>(); private final ConcurrentHashMap<Object, Timeout> timerKey2Timeouts = new ConcurrentHashMap<>();
@Autowired public Scheduler(final PmLocalServerSDKConfig pmLocalServerSDKConfig) { final PmLocalServerSDKConfig.SchedulerConfig schedulerConfig = pmLocalServerSDKConfig.getScheduler(); final int tickInMillis = Math.max(1, schedulerConfig.getTickDurationInMillis()); final int ticksPerWheel = Math.max(512, schedulerConfig.getTicksPerWheel()); this.hashedWheelTimer = new HashedWheelTimer( new NamedThreadFactory('localserver-scheduler'), tickInMillis, TimeUnit.MILLISECONDS, ticksPerWheel ); }
public boolean cancel(final Long timerId) { final Timeout timeout = timerId2Timeout.remove(timerId); if (timeout != null) { timeout.cancel(); return true; } return false; }
public boolean cancel(final Object timerKey) { final Timeout timeout = timerKey2Timeouts.remove(timerKey); if (timeout != null) { timeout.cancel(); return true; } return false; }
public Long scheduleOnce(final Duration delay, final Runnable runnable, final Context context) { Objects.requireNonNull(delay, 'delay should not be null.'); Objects.requireNonNull(runnable, 'runnable should not be null.'); Objects.requireNonNull(context, 'context should not be null.'); final Long timerId = timerIdGen.incrementAndGet(); timerId2Timeout.compute(timerId, (key, timeout) -> hashedWheelTimer.newTimeout(t -> { Optional.ofNullable(timerId2Timeout.remove(timerId)).ifPresent(Timeout::cancel); context.runOnContext(event -> { runnable.run(); }); }, delay.toNanos(), TimeUnit.NANOSECONDS)); return timerId; }
public void scheduleOnce(final Object timerKey, final Duration delay, final Runnable runnable, final Context context) { Objects.requireNonNull(timerKey, 'timerKey should not be null.'); Objects.requireNonNull(delay, 'delay should not be null.'); Objects.requireNonNull(runnable, 'runnable should not be null.'); Objects.requireNonNull(context, 'context should not be null.'); timerKey2Timeouts.computeIfAbsent( timerKey, (key) -> hashedWheelTimer.newTimeout(t -> { context.runOnContext(event -> { timerKey2Timeouts.remove(timerKey); runnable.run(); }); }, delay.toNanos(), TimeUnit.NANOSECONDS) ); }
public Long scheduleWithFixDelay(final Duration initialDelay, final Duration delay, final Runnable runnable, final Context context) { Objects.requireNonNull(initialDelay, 'initialDelay should not be null.'); Objects.requireNonNull(delay, 'delay should not be null.'); Objects.requireNonNull(runnable, 'runnable should not be null.'); Objects.requireNonNull(context, 'context should not be null.'); final Long timerId = timerIdGen.incrementAndGet(); final Runnable scheduledRunnable = new Runnable() { final Runnable self = this;
@Override public void run() { try { runnable.run(); } catch (Exception e) { log.error('Error when trigger task of runnable:[{}]', runnable, e); } finally { timerId2Timeout.computeIfPresent(timerId, (key, timeout) -> { tryCancel(timeout); return scheduleWithTimerId(delay, self, context); }); } } }; timerId2Timeout.compute(timerId, (key, timeout) -> scheduleWithTimerId(initialDelay, scheduledRunnable, context)); return timerId; }
public void scheduleWithFixDelay(final Object timerKey, final Duration initialDelay, final Duration delay, final Runnable runnable, final Context context) { Objects.requireNonNull(timerKey, 'timerKey should not be null.'); Objects.requireNonNull(initialDelay, 'initialDelay should not be null.'); Objects.requireNonNull(delay, 'delay should not be null.'); Objects.requireNonNull(runnable, 'runnable should not be null.'); Objects.requireNonNull(context, 'context should not be null.'); final Runnable scheduledRunnable = new Runnable() { final Runnable self = this;
@Override public void run() { try { runnable.run(); } catch (Exception e) { log.error('Error when trigger task of runnable:[{}]', runnable, e); } finally { timerKey2Timeouts.computeIfPresent( timerKey, (key, timeout) -> { tryCancel(timeout); return scheduleWithTimerKey(delay, self, context); }); } } };
timerKey2Timeouts.computeIfAbsent(timerKey, (key) -> scheduleWithTimerKey(initialDelay, scheduledRunnable, context)); }
private boolean tryCancel(final Timeout timeout) { if (timeout != null) { return timeout.cancel(); } return true; }
private Timeout scheduleWithTimerId(final Duration delay, final Runnable runnable, final Context context) { return hashedWheelTimer.newTimeout( t -> context.runOnContext(event -> runnable.run()), delay.toNanos(), TimeUnit.NANOSECONDS); }
private Timeout scheduleWithTimerKey(final Duration delay, final Runnable runnable, final Context context) { return hashedWheelTimer.newTimeout( t -> context.runOnContext(event -> runnable.run()), delay.toNanos(), TimeUnit.NANOSECONDS); }
@PostConstruct protected void init() { hashedWheelTimer.start(); }
@PreDestroy protected void stop() { final Set<Timeout> timeouts = hashedWheelTimer.stop(); if (CollectionUtils.isNotEmpty(timeouts)) { for (Timeout timeout : timeouts) { if (timeout.isCancelled() || timeout.isExpired()) { continue; } final TimerTask task = timeout.task(); try { task.run(timeout); } catch (Exception e) { //Ignore } } }
原文地址: https://www.cveoy.top/t/topic/lH45 著作权归作者所有。请勿转载和采集!