org.conqat.lib.commons.concurrent.ThreadUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of teamscale-lib-commons Show documentation
Show all versions of teamscale-lib-commons Show documentation
Provides common utility functions
/*
* Copyright (c) CQSE GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.conqat.lib.commons.concurrent;
import java.time.Duration;
import java.util.function.BooleanSupplier;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.conqat.lib.commons.assertion.CCSMAssert;
/**
* Utility methods for dealing with threads.
*/
public class ThreadUtils {
/**
* Causes the current thread to sleep the given number of milliseconds. The sleep phase can also
* exit earlier if an {@link InterruptedException} is thrown. Any {@link InterruptedException} is
* silently discarded.
*/
public static void sleep(long milliseconds) {
try {
Thread.sleep(milliseconds);
} catch (InterruptedException e) {
// ignore exception
}
}
/**
* Puts the thread to sleep but regularly polls for cancels using {@code cancelTokenSupplier} in
* case the caller issued a cancel request.
*
* @param delay
* complete duration to sleep
* @param pollingInterval
* interval at which the {@code cancelTokenSupplier} should be queried
* @param cancelTokenSupplier
* Supplier indicating whether the sleep should stop before the complete {@code delay}
* finished
* @return Whether the complete {@code delay} was slept ({@code true}) or stopped by the
* {@code cancelTokenSupplier} ({@code false})
*/
public static boolean cancelableSleep(@NonNull Duration delay, @NonNull Duration pollingInterval,
@NonNull BooleanSupplier cancelTokenSupplier) throws InterruptedException {
CCSMAssert.isNotNull(delay, () -> String.format("Expected \"%s\" to be not null", "delay"));
CCSMAssert.isNotNull(pollingInterval, () -> String.format("Expected \"%s\" to be not null", "pollingInterval"));
CCSMAssert.isNotNull(cancelTokenSupplier,
() -> String.format("Expected \"%s\" to be not null", "cancelTokenSupplier"));
if (delay.isZero() || delay.isNegative()) {
throw new IllegalArgumentException("delay must be positive");
}
if (pollingInterval.isZero() || pollingInterval.isNegative()) {
throw new IllegalArgumentException("pollingInterval must be positive");
}
for (Duration remainingDelay = delay; !remainingDelay.isZero()
&& !remainingDelay.isNegative(); remainingDelay = remainingDelay.minus(pollingInterval)) {
if (remainingDelay.compareTo(pollingInterval) < 0) {
sleep(remainingDelay);
} else {
sleep(pollingInterval);
}
if (cancelTokenSupplier.getAsBoolean()) {
return false;
}
}
return true;
}
/**
* Same as {@link Thread#sleep(long)}, but converts the given duration to millis.
*
* @see Thread#sleep(long)
*/
public static void sleep(Duration duration) throws InterruptedException {
Thread.sleep(duration.toMillis());
}
}