package com.kodcu.service; import javafx.application.Platform; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.concurrent.Task; import javafx.event.ActionEvent; import javafx.scene.Scene; import javafx.scene.web.WebView; import org.springframework.stereotype.Component; import java.util.Objects; import java.util.concurrent.*; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; /** * Created by usta on 25.12.2014. */ @Component public class ThreadService { private final ExecutorService threadPollWorker; private final ScheduledExecutorService scheduledWorker; private final ConcurrentHashMap<String, Buff> buffMap; private final Semaphore uiSemaphore; private final ExecutorService singleExecutor; public ThreadService() { scheduledWorker = Executors.newSingleThreadScheduledExecutor(); threadPollWorker = Executors.newWorkStealingPool(16); singleExecutor = Executors.newSingleThreadExecutor(); uiSemaphore = new Semaphore(1); buffMap = new ConcurrentHashMap<>(); } public ScheduledFuture<?> schedule(Runnable runnable, long delay, TimeUnit timeUnit) { return scheduledWorker.schedule(runnable, delay, timeUnit); } public ScheduledFuture<?> scheduleWithDelay(Runnable runnable, long initialDelay, long delay, TimeUnit timeUnit) { return scheduledWorker.scheduleWithFixedDelay(runnable, initialDelay, delay, timeUnit); } // Runs Task in background thread pool public <T> Future<?> runTaskLater(Runnable runnable) { Task<T> task = new Task<T>() { @Override protected T call() throws Exception { runnable.run(); return null; } }; task.exceptionProperty().addListener((observable, oldValue, newValue) -> { if (Objects.nonNull(newValue)) { newValue.printStackTrace(); } }); return threadPollWorker.submit(task); } // Runs task in JavaFX Thread public void runActionLater(Consumer<ActionEvent> consumer) { runActionLater(() -> { consumer.accept(null); }); } // Runs task in JavaFX Thread public void runActionLater(final Runnable runnable) { if (Platform.isFxApplicationThread()) { runnable.run(); } else { try { uiSemaphore.acquire(); Platform.runLater(() -> { try { runnable.run(); releaseUiSemaphore(); } catch (Exception e) { releaseUiSemaphore(); throw new RuntimeException(e); } }); } catch (Exception e) { releaseUiSemaphore(); throw new RuntimeException(e); } } } private void releaseUiSemaphore() { singleExecutor.submit(() -> { uiSemaphore.release(); }); } public void runActionLater(Runnable runnable, boolean force) { if (force) { Platform.runLater(runnable); } else { runActionLater(runnable); } } public void start(Runnable runnable) { Thread thread = new Thread(runnable); thread.start(); } public Executor executor() { return threadPollWorker; } public static void sleep(int ms) { try { Thread.sleep(ms); } catch (InterruptedException e) { // logger.error("Error in Thread#sleep", e); } } public Buff buff(String id) { buffMap.putIfAbsent(id, new Buff(this)); return buffMap.get(id); } public <T> T supply(Supplier<T> supplier) { if (Platform.isFxApplicationThread()) { return supplier.get(); } final CompletableFuture<T> completableFuture = new CompletableFuture<T>(); completableFuture.runAsync(() -> { runActionLater(() -> { try { T t = supplier.get(); completableFuture.complete(t); } catch (Exception e) { completableFuture.completeExceptionally(e); } }); }, threadPollWorker); return completableFuture.join(); } public <T> void runActionLater(Consumer<T> consumer, T t) { runActionLater(() -> { consumer.accept(t); }); } public ScheduledFuture<?> scheduleWithDelay(Runnable runnable, int timeBetweenFramesMS, TimeUnit milliseconds) { return scheduleWithDelay(runnable, 0, timeBetweenFramesMS, milliseconds); } }