Created
April 23, 2016 15:54
-
-
Save vladimir-bukhtoyarov/f5a3163d665c28794cda7fa5e024b56c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.lang.ref.WeakReference; | |
import java.util.concurrent.*; | |
import java.util.function.Consumer; | |
public class SchedulerLeakProtector { | |
public static <T> ScheduledFuture<?> scheduleAtFixedRate(ScheduledExecutorService scheduler, T target, Consumer<T> consumer, long initialDelay, long period, TimeUnit timeUnit) { | |
CompletableFuture<ScheduledFuture<?>> scheduledFutureFuture = new CompletableFuture<>(); | |
LeakProtectedRunnable<T> runnable = new LeakProtectedRunnable<>(target, consumer, scheduledFutureFuture); | |
ScheduledFuture<?> scheduledFuture = scheduler.scheduleAtFixedRate(runnable, initialDelay, period, timeUnit); | |
scheduledFutureFuture.complete(scheduledFuture); | |
return scheduledFuture; | |
} | |
private static final class LeakProtectedRunnable<T> implements Runnable { | |
private final WeakReference<T> targetReference; | |
private final Consumer<T> consumer; | |
private final CompletableFuture<ScheduledFuture<?>> scheduledFutureFuture; | |
LeakProtectedRunnable(T target, Consumer<T> consumer, CompletableFuture<ScheduledFuture<?>> scheduledFutureFuture) { | |
this.targetReference = new WeakReference<>(target); | |
this.consumer = consumer; | |
this.scheduledFutureFuture = scheduledFutureFuture; | |
} | |
@Override | |
public void run() { | |
T target = targetReference.get(); | |
if (target != null) { | |
// target object still strong referenced | |
consumer.accept(target); | |
return; | |
} | |
// target object became unreachable lets cancel scheduled task | |
try { | |
scheduledFutureFuture.get().cancel(false); | |
} catch (Exception e) { | |
throw new IllegalStateException(e); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Sometimes you need to do something periodical work under object until it strongly referenced. But adding new scheduled task to executor leads to creation new strong reference, so object has no chanses to became unreachable. This utility class protect object from leak strong reference through ScheduledExecutorService.