/** {@inheritDoc} */ @Override public void run() { while (!this.isShutdown) { // handle "everything is empty" this.addLock.lock(); try { // sleep if there is nothing to do while (this.pool.size() + this.queue.size() + this.add.size() + this.addQueue.size() == 0) { if (this.threadIsEmpty.awaitNanos(TimeUnit.MINUTES.toNanos(2)) <= 0 || this.isShutdown) { this.isShutdown = true; this.pool.clear(); return; } } this.pool.addAll(this.add); this.add.clear(); this.queue.addAll(this.addQueue); this.addQueue.clear(); } catch (InterruptedException e) { this.isShutdown = true; this.pool.clear(); this.queue.clear(); return; } finally { this.addLock.unlock(); } // remove jobs on request this.removeLock.lock(); try { this.pool.removeAll(this.remove); Iterator<Entry> iter = this.queue.iterator(); while (iter.hasNext()) if (this.remove.contains(iter.next().job)) iter.remove(); this.remove.clear(); } finally { this.removeLock.unlock(); } // first handle normal jobs Iterator<IDoJob> poolIT = this.pool.iterator(); while (poolIT.hasNext()) { IDoJob job = poolIT.next(); if (!job.isfinished()) try { job.doJob(); } catch (Exception e) { LOGGER.severe( "The job " + job.name() + " threw an exception and has been subsequently removed.", e); poolIT.remove(); this._shutdownJob(job); } else poolIT.remove(); } if (!this.queue.isEmpty()) { final long ctime = Platform.currentTime(); // first work on jobs that are overdue Iterator<Entry> queueIT = this.queue.iterator(); while (queueIT.hasNext()) { Entry entry = queueIT.next(); if (entry.time > ctime) break; queueIT.remove(); if (!entry.job.isfinished()) { try { if (entry.loop != Entry.NO_LOOP) { entry.job.doJob(); entry.time = Math.max(entry.time + entry.loop, ctime); entry._decipher = Entry.DECIPHER++; this.addLock.lock(); try { this.addQueue.add(entry); } finally { this.addLock.unlock(); } } else this.addJob(entry.job); } catch (Exception e) { LOGGER.severe( "The job " + entry.job.name() + " threw an exception and has been subsequently removed.", e); this._shutdownJob(entry.job); } } } } this.addLock.lock(); try { long time = 0; // we need to sleep when there are jobs in the queue that should not be worked on yet, but // there are no jobs in the pool while (this.pool.size() + this.add.size() + this.addQueue.size() == 0 && !this.queue.isEmpty() && (time = this.queue.peek().time - Platform.currentTime()) > 5) { this.threadIsEmpty.await(time, TimeUnit.MILLISECONDS); } } catch (InterruptedException e) { // do nothing just check the conditions above } finally { this.addLock.unlock(); } } for (IDoJob job : this.pool) this._shutdownJob(job); for (Entry entry : this.queue) this._shutdownJob(entry.job); this.pool.clear(); this.queue.clear(); }