All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.xqbase.util.Runnables Maven / Gradle / Ivy

There is a newer version: 0.2.18
Show newest version
package com.xqbase.util;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import com.xqbase.util.function.Consumer;
import com.xqbase.util.function.RunnableEx;
import com.xqbase.util.function.SupplierEx;

public class Runnables {
	static AtomicInteger threadNum = new AtomicInteger(0);

	/**
	 * @return Number of wrapped and active branch thread
	 * @see #wrap(Runnable)
	 */
	public static int getThreadNum() {
		return threadNum.get();
	}

	/**
	 * Wrap a {@link Runnable} in order to:
	 * 
    *
  • Make the logging suffix in branch thread (callee thread) * the same as trunk thread (caller thread)
  • *
  • Make the logging stack trace in branch thread * concatenating with trunk thread
  • *
  • Count number of branch threads
  • *
* * @see Log#suffix * @see Log#throwable */ public static Runnable wrap(final Runnable runnable) { final String suffix = Log.suffix.get(); // t.getCause() is atop t, see Log.concat() for more details final Throwable t = new Throwable(Log.throwable.get()); return new Runnable() { @Override public void run() { threadNum.incrementAndGet(); Log.suffix.set(suffix); Log.throwable.set(t); try { runnable.run(); } catch (Error | RuntimeException e) { Log.e(e); } finally { Log.throwable.remove(); Log.suffix.remove(); threadNum.decrementAndGet(); } } }; } /** * Wrap a {@link Callable} * * @see #wrap(Runnable) */ public static Callable wrap(final Callable callable) { final String suffix = Log.suffix.get(); // t.getCause() is atop t, see Log.concat() for more details final Throwable t = new Throwable(Log.throwable.get()); return new Callable() { @Override public V call() throws Exception { threadNum.incrementAndGet(); Log.suffix.set(suffix); Log.throwable.set(t); try { return callable.call(); } catch (Error e) { throw new Exception(e); } finally { Log.throwable.remove(); Log.suffix.remove(); threadNum.decrementAndGet(); } } }; } @SuppressWarnings("unchecked") private static U cast(T o) { return (U) o; } public static void retry(final RunnableEx runnable, Consumer handler, int count, int interval) throws E { retry(new SupplierEx() { @Override public Void get() throws E { runnable.run(); return null; } }, handler, count, interval); } public static T retry(SupplierEx supplier, Consumer handler, int count, int interval) throws E { for (int i = 0; i < count; i ++) { try { return supplier.get(); } catch (Exception e) { if (e instanceof RuntimeException) { throw e; } handler.accept(Runnables.cast(e)); if (interval > 0) { Time.sleep(interval); } } } return supplier.get(); } private static void awaitTermination(ExecutorService service) { boolean interrupted = Thread.interrupted(); boolean terminated = false; while (!terminated) { try { terminated = service.awaitTermination(1, TimeUnit.SECONDS); } catch (InterruptedException e) { interrupted = true; } } if (interrupted) { Thread.currentThread().interrupt(); } } /** * Shutdown and wait for a {@link ExecutorService} like {@link ExecutorService#shutdown()} * and {@link ExecutorService#awaitTermination(long, TimeUnit)} but ignore interruption

* The interrupted status will not be cleared if current thread is interrupted during shutdown */ public static void shutdown(ExecutorService service) { service.shutdown(); awaitTermination(service); } /** * Shutdown immediately and wait for a {@link ExecutorService} like {@link ExecutorService#shutdownNow()} * and {@link ExecutorService#awaitTermination(long, TimeUnit)} but ignore interruption

* The interrupted status will not be cleared if current thread is interrupted during shutdown */ public static void shutdownNow(ExecutorService service) { service.shutdownNow(); awaitTermination(service); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy