@Override
	public void run() {
		synchronized (this) {
			if (mWasCancelled) {
				return;
			}
			mWasExecuted = true;
		}
		try {
			if (mKey != null) {
				synchronized (PENDING) {
					PENDING.remove(mKey);
				}
			}
			if (isPeriodic()) {
				long next = System.currentTimeMillis() + mPeriod;
				mTask.run();
				EXECUTOR.schedule(this, Math.max(next - System.currentTimeMillis(), 0), TimeUnit.MILLISECONDS);
			} else {
				mTask.run();
			}
		} catch (Throwable throwable) {
			cancel();
			Log.error(throwable);
		}
	}