Scheduled action no interrupt

At the end of the run, ScheduledAction unsubscribes itself which triggers a set of cleanup actions, and since it is also the way to cancel a running action, it calls future.cancel(true) as well which interrupts the task in the underlying executor framework. However, on a normal completion path, it is unnecessary to interrupt itself at the end of the run since it will complete anyway, and not to mention, it has some performance implications for short running tasks. The downside is the +4 bytes per ScheduledAction.
On X86, volatile read cost the same as any regular memory read. CAS is around 20-40 cycles. I've run a small program and measured always failing and always succeding CAS on my i7 4770 @ 3.5GHz and gave me ~5.2 ns in both cases, If I test the variable before CAS, I get 1.6ns for always fails and 8.8ns for always succeeding. So for 2 unsubscribe calls, we get 10.4ns in the CAS only case and 10.4ns with read-before-cas. However, any additional unsubscribe calls adds only 1.6ns with read-before-cas instead of 5.2ns. I must admit, the 2 unsubscribe calls costing the same time suprises me.

The unsubscribe() is still idempotent because either cancel.isUnsubscribed returns true and nothing happens or cancel.unsubscribe() is called which *is* idempotent.

```java
public class CasFailureTest {
	public static void main(String[] args) {
		AtomicInteger v = new AtomicInteger(0);
//		AtomicInteger v = new AtomicInteger(1);
		
		int k = 100_000_000;
		for (int i = 0; i < 10; i++) {
			long n = System.nanoTime();
			for (int j = 0; j < k; j++) {
				if (v.get() == j) {
					v.compareAndSet(j, j + 1);
				}
//				if (v.get() == 0)
//					v.compareAndSet(0, 1);
			}
			System.out.println(1d * (System.nanoTime() - n) / k);
			v.set(0);
		}
	}
}
```