package com.framsticks.util.dispatching; import org.apache.log4j.Logger; import java.util.LinkedList; import java.util.ListIterator; import com.framsticks.util.dispatching.RunAt; /** * @author Piotr Sniegowski */ public class Thread implements Dispatcher { private static final Logger log = Logger.getLogger(Thread.class.getName()); protected final java.lang.Thread thread; private final LinkedList> queue = new LinkedList<>(); public Thread() { thread = new java.lang.Thread(new java.lang.Runnable() { @Override public void run() { Thread.this.routine(); } }); } public Thread(String s) { this(); thread.setName(s); // thread.start(); } public Thread(String s, java.lang.Thread thread) { this.thread = thread; thread.setName(s); } public Thread start() { thread.start(); return this; } @Override public final boolean isActive() { return thread.equals(java.lang.Thread.currentThread()); } protected void routine() { while (!java.lang.Thread.interrupted()) { Task task; synchronized (queue) { if (queue.isEmpty()) { try { queue.wait(); } catch (InterruptedException ignored) { break; } continue; } task = queue.peekFirst(); assert task != null; if (task.moment > System.currentTimeMillis()) { try { queue.wait(task.moment - System.currentTimeMillis()); } catch (InterruptedException ignored) { continue; } continue; } queue.pollFirst(); } try { task.run(); } catch (Exception e) { log.error("error in thread: " + e); e.printStackTrace(); } } } protected void enqueueTask(Task task) { synchronized (queue) { ListIterator> i = queue.listIterator(); while (i.hasNext()) { Task t = i.next(); if (t.getMoment() > task.getMoment()) { i.previous(); i.add(task); task = null; break; } } if (task != null) { queue.add(task); } /* Iterator j = queue.iterator(); Task prev = null; while (j.hasNext()) { Task next = j.next(); assert (prev == null) || prev.getMoment() <= next.getMoment(); prev = next; } */ queue.notify(); } } @Override public void invokeLater(final RunAt runnable) { if (!(runnable instanceof Task)) { enqueueTask(new Task() { @Override public void run() { runnable.run(); } }); return; } enqueueTask((Task) runnable); } public void interrupt() { thread.interrupt(); } public void join() throws InterruptedException { thread.join(); } public void setName(String name) { thread.setName(name); } public static boolean interrupted() { return java.lang.Thread.interrupted(); } }