docs: @PostConstruct
      public final void init() {
          long timeToKeepAfterAccessInMillis = this.jobQueue.getTimeToKeepAfterAccessInMillis();
          if (timeToKeepAfterAccessInMillis >= 0) {
              if (TimeUnit.SECONDS.toMillis(this.abandonedTimeout) >=
                      this.jobQueue.getTimeToKeepAfterAccessInMillis()) {
                  final String msg =
                          String.format("%s abandonTimeout must be smaller than %s timeToKeepAfterAccess",
                                        getClass().getName(), this.jobQueue.getClass().getName());
                  throw new IllegalStateException(msg);
              }
              if (TimeUnit.SECONDS.toMillis(this.timeout) >= this.jobQueue.getTimeToKeepAfterAccessInMillis()) {
                  final String msg = String.format("%s timeout must be smaller than %s timeToKeepAfterAccess",
                                                   getClass().getName(), this.jobQueue.getClass().getName());
                  throw new IllegalStateException(msg);
              }
          }
          CustomizableThreadFactory threadFactory = new CustomizableThreadFactory();
          threadFactory.setDaemon(true);
          threadFactory.setThreadNamePrefix("PrintJobManager-");
  
          PriorityBlockingQueue<Runnable> queue =
                  new PriorityBlockingQueue<>(
                          this.maxNumberOfWaitingJobs,
                          (o1, o2) -> {
                              if (o1 instanceof JobFutureTask<?> &&
                                      o2 instanceof JobFutureTask<?>) {
                                  Callable<?> callable1 = ((JobFutureTask<?>) o1).getCallable();
                                  Callable<?> callable2 = ((JobFutureTask<?>) o2).getCallable();
  
                                  if (callable1 instanceof PrintJob) {
                                      if (callable2 instanceof PrintJob) {
                                          return ThreadPoolJobManager.this.jobPriorityComparator
                                                  .compare((PrintJob) callable1,
                                                           (PrintJob) callable2);
                                      }
                                      return 1;
                                  } else if (callable2 instanceof PrintJob) {
                                      return -1;
                                  }
                              }
                              return 0;
                          });
          /* The ThreadPoolExecutor uses a unbounded queue (though we are enforcing a limit in `submit()`).
           * Because of that, the executor creates only `corePoolSize` threads. But to use all threads,
           * we set both `corePoolSize` and `maximumPoolSize` to `maxNumberOfRunningPrintJobs`. As a
           * consequence, the `maxIdleTime` will be ignored, idle threads will not be terminated.
           */
          this.executor =
                  new ThreadPoolExecutor(this.maxNumberOfRunningPrintJobs, this.maxNumberOfRunningPrintJobs,
                                         this.maxIdleTime, TimeUnit.SECONDS, queue, threadFactory) {
                      @Override
                      protected <T> RunnableFuture<T> newTaskFor(final Callable<T> callable) {
                          return new JobFutureTask<>(callable);
                      }
  
                      @Override
                      protected void beforeExecute(final Thread t, final Runnable runnable) {
                          if (!ThreadPoolJobManager.this.clustered && runnable instanceof JobFutureTask<?>) {
                              JobFutureTask<?> task = (JobFutureTask<?>) runnable;
                              if (task.getCallable() instanceof PrintJob) {
                                  PrintJob printJob = (PrintJob) task.getCallable();
                                  try {
                                      ThreadPoolJobManager.this.jobQueue
                                              .start(printJob.getEntry().getReferenceId());
                                  } catch (RuntimeException e) {
                                      LOGGER.error("failed to mark job as running", e);
                                  } catch (NoSuchReferenceException e) {
                                      LOGGER.error("tried to mark non-existing job as 'running': {}",
                                                   printJob.getEntry().getReferenceId(), e);
                                  }
                              }
                          }
                          super.beforeExecute(t, runnable);
                      }
                  };
  
          this.timer = Executors.newScheduledThreadPool(1, timerTask -> {
              final Thread thread = new Thread(timerTask, "Post result to registry");
              thread.setDaemon(true);
              return thread;
          });
          this.timer.scheduleAtFixedRate(new RegistryTask(), RegistryTask.CHECK_INTERVAL,
                                         RegistryTask.CHECK_INTERVAL, TimeUnit.MILLISECONDS);
  
          if (this.oldFileCleanUp) {
              this.cleanUpTimer = Executors.newScheduledThreadPool(1, timerTask -> {
                  final Thread thread = new Thread(timerTask, "Clean up old files");
                  thread.setDaemon(true);
                  return thread;
              });
              this.cleanUpTimer.scheduleAtFixedRate(
                      this.workingDirectories.getCleanUpTask(), 0,
                      this.oldFileCleanupInterval, TimeUnit.SECONDS);
          }
      }