package org.smartly.commons.async; import org.smartly.commons.Delegates; import org.smartly.commons.util.MathUtils; import java.util.HashSet; import java.util.Set; /** * Utility class to run async methods */ public abstract class Async { public static Thread Action(final Delegates.Action handler, final Object... args) { if (null != handler) { final Thread t = new Thread(new Runnable() { @Override public void run() { handler.handle(args); } }); t.setDaemon(true); t.setPriority(Thread.NORM_PRIORITY); t.start(); return t; } return null; } public static void Delay(final Delegates.Action handler, final int delay, final Object... args) { if (null != handler) { final Thread t = new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(delay); handler.handle(args); } catch (Throwable ignored) { } } }); t.setDaemon(true); t.setPriority(Thread.NORM_PRIORITY); t.start(); } } public static void maxConcurrent(final Thread[] threads, final int maxConcurrentThreads) { maxConcurrent(threads, maxConcurrentThreads, null); } public static void maxConcurrent(final Thread[] threads, final int maxConcurrentThreads, final Delegates.ProgressCallback onProgress) { final int len = threads.length; //-- Async execution --// Action(new Delegates.Action() { @Override public void handle(Object... args) { final int max = maxConcurrentThreads <= len ? maxConcurrentThreads : len; final Thread[] concurrent = new Thread[max]; int count = 0; for (int i = 0; i < len; i++) { concurrent[count] = threads[i]; count++; if (count == max) { startAll(concurrent); joinAll(concurrent); count = 0; } if (null != onProgress) { onProgress.handle(i, len, MathUtils.progress(i + 1, len, 2)); } } } }); } public static Thread[] maxConcurrent(final int length, final int maxConcurrentThreads, final Delegates.CreateRunnableCallback runnableFunction) { if (null == runnableFunction) { return new Thread[0]; } final Thread[] result = new Thread[length]; final int max = maxConcurrentThreads <= length ? maxConcurrentThreads : length; final Thread[] concurrent = new Thread[max]; int count = 0; for (int i = 0; i < length; i++) { final Runnable runnable = runnableFunction.handle(i, length); final Thread t = (runnable instanceof Thread) ? (Thread) runnable : new Thread(runnable); result[i] = t; concurrent[count] = t; count++; if (count == max || (i + 1) == length) { startAll(concurrent); joinAll(concurrent); count = 0; } } return result; } public static void startAll(final Thread[] threads) { for (final Thread thread : threads) { try { if (!thread.isAlive() && !thread.isInterrupted()) { thread.start(); } } catch (Throwable ignored) { } } } public static void joinAll(final Thread[] threads) { final int length = threads.length; final Set<Long> terminated = new HashSet<Long>(); while (length > terminated.size()) { for (final Thread thread : threads) { try { final Thread.State state = thread.getState(); if (Thread.State.RUNNABLE.equals(state)) { thread.join(); } else if (Thread.State.TERMINATED.equals(state)) { terminated.add(thread.getId()); } else { System.out.println(state); } } catch (Throwable ignored) { } } } } }