Timer can exhaust the system with TimerTask-runnables that are queued up
e.g. during computer hibernate and sleep. According to documentation:
If an execution is delayed for any reason (such as garbage collection or
other background activity), two or more executions will occur in rapid
succession to "catch up." In the long run, the frequency of execution
will be exactly the reciprocal of the specified period
With heavy tasks this is very bad
refs #7682
Change-Id: I5a097c8bc5e1ea2a5abe30905b2a46fa8b8386f8
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
-import java.util.Timer;
-import java.util.TimerTask;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
import org.simantics.g2d.canvas.Hints;
import org.simantics.g2d.canvas.ICanvasContext;
import org.simantics.g2d.canvas.Hints;
import org.simantics.g2d.canvas.ICanvasContext;
import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;
import org.simantics.g2d.canvas.impl.HintReflection.HintListener;
import org.simantics.utils.datastructures.disposable.DisposeState;
import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;
import org.simantics.g2d.canvas.impl.HintReflection.HintListener;
import org.simantics.utils.datastructures.disposable.DisposeState;
-import org.simantics.utils.datastructures.hints.IHintObservable;
import org.simantics.utils.datastructures.hints.IHintContext.Key;
import org.simantics.utils.datastructures.hints.IHintContext.Key;
+import org.simantics.utils.datastructures.hints.IHintObservable;
import org.simantics.utils.threads.IThreadWorkQueue;
/**
import org.simantics.utils.threads.IThreadWorkQueue;
/**
long lastTrigger;
Point2D centerPoint = new Point2D.Double();
long lastTrigger;
Point2D centerPoint = new Point2D.Double();
- transient Timer timer = new Timer("Rotate restore");
+ transient ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor();
transient boolean checkRotatePending = false;
transient boolean checkRotatePending = false;
- TimerTask task = new TimerTask() {
+ Runnable task = new Runnable() {
@Override
public void run() {
ICanvasContext ctx = getContext();
@Override
public void run() {
ICanvasContext ctx = getContext();
@Override
public void removedFromContext(ICanvasContext ctx) {
@Override
public void removedFromContext(ICanvasContext ctx) {
+ timer.shutdown();
+ try {
+ if (!timer.awaitTermination(1, TimeUnit.SECONDS)) {
+ timer.shutdownNow();
+ }
+ } catch (InterruptedException e) {
+ // Ignore
+ }
super.removedFromContext(ctx);
}
@Override
public void addedToContext(ICanvasContext ctx) {
super.addedToContext(ctx);
super.removedFromContext(ctx);
}
@Override
public void addedToContext(ICanvasContext ctx) {
super.addedToContext(ctx);
- long delay = 1000 / 25;
+// long delay = 1000 / 25; this sounds quite frequent
+ long delay = 1000 / 10;
lastTrigger = System.currentTimeMillis();
lastTrigger = System.currentTimeMillis();
- timer.scheduleAtFixedRate(task, delay, delay);
+ timer.scheduleAtFixedRate(task, delay, delay, TimeUnit.MILLISECONDS);
}
@HintListener(Class = Hints.class, Field = "KEY_CANVAS_BOUNDS")
}
@HintListener(Class = Hints.class, Field = "KEY_CANVAS_BOUNDS")