package com.framsticks.util.dispatching; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import com.framsticks.params.annotations.ParamAnnotation; import com.framsticks.util.dispatching.RunAt; /** * @author Piotr Sniegowski */ public class Thread extends AbstractJoinable implements Dispatcher { private static final Logger log = LogManager.getLogger(Thread.class); protected final java.lang.Thread thread; protected final Object condition = new Object(); private RunnableQueue queue = new RunnableQueue<>(); public Thread() { thread = new java.lang.Thread(new Runnable() { @Override public void run() { Thread.this.routine(); } }); } public Thread(java.lang.Thread thread) { this.thread = thread; } @Override protected void joinableStart() { thread.start(); } @Override public final boolean isActive() { return thread.equals(java.lang.Thread.currentThread()); } protected void routine() { log.debug("starting thread {}", this); assert getMonitor() != null; ExceptionHandler exceptionHandler = getMonitor().getTaskExceptionHandler(); while (!java.lang.Thread.interrupted()) { RunAt runnable; synchronized (condition) { if (queue.isEmpty()) { try { condition.wait(); } catch (InterruptedException ignored) { break; } continue; } runnable = queue.pollFirst(); } if (runnable != null) { try { runnable.run(); } catch (Exception e) { if (exceptionHandler != null) { if (exceptionHandler.handle(this, e)) { continue; } } log.error("error in thread: ", e); } } } log.debug("finishing thread {}", this); finishJoinable(); } @Override public void dispatch(RunAt runnable) { synchronized (condition) { queue.push(runnable); condition.notifyAll(); } } public RunnableQueue switchQueue(RunnableQueue queue) { synchronized (condition) { RunnableQueue result = this.queue; this.queue = queue; return result; } } @Override protected void joinableInterrupt() { thread.interrupt(); } @Override protected void joinableJoin() throws InterruptedException { thread.join(500); log.debug("joined {}", this); } @ParamAnnotation public Thread setName(String name) { thread.setName(name); return this; } @ParamAnnotation public String getName() { return thread.getName(); } public static boolean interrupted() { return java.lang.Thread.interrupted(); } // @Override // public String toString() { // return getName(); // } @Override protected void joinableFinish() { } }