public abstract class Plugin implements Runnable, IDataOperation.DataChangeListener { protected PluginProperties properties = new PluginProperties(this); private boolean isRunning = false; private long waitMillis = 0; private Thread pluginThread = null; public PluginProperties getProperties() { return properties; } public boolean isRunning() { return isRunning; } public void setRunning(boolean isRunning) { this.isRunning = isRunning; } protected Plugin() { if (properties.getName() == null || properties.getName().isEmpty()) { properties.setName(getClass().getName()); } onCreated(); } protected void onCreated() { } public abstract void start(); public abstract void end(); public abstract void update(); @Override public final void run() { pluginThread = Thread.currentThread(); start(); while (isRunning) { synchronized (pluginThread) { try { update(); pluginThread.wait(properties.getExecuteInterval().toStandardDuration().getMillis()); } catch (InterruptedException ex) { Logger.getLogger(Plugin.class.getName()).log(Level.SEVERE, null, ex); } } } end(); } @Override public void OnIntervalChange(long newIntervallMillis) { waitMillis = newIntervallMillis; } }