title: How to create a blocking background loader in Java 8?
body: <p><strong><em>Question</em></strong></p>
  
  <p>How do you create a proper background loader in Java 8? The conditions:</p>
  
  <ul>
  <li>data should be loaded in background</li>
  <li>after the loading the data should be displayed</li>
  <li>while data are loaded no further requests should be accepted</li>
  <li>if there were requests while the data were loaded another loading should be scheduled after a certain timeout (e. g. 5 seconds)</li>
  </ul>
  
  <p>The purpose is to e. g. have reload requests accepted, but not the database flooded with the requests.</p>
  
  <p><strong><em>MCVE</em></strong></p>
  
  <p>Here's a MCVE. It consists of a background task which simulates the loading by simply invoking Thread.sleep for 2 seconds. The task is scheduled every second which naturally leads to an overlap of the background loading tasks, which should be avoided.</p>
  
  <pre><code>public class LoadInBackgroundExample {
  
    /**
     * A simple background task which should perform the data loading operation. In this minimal example it simply invokes Thread.sleep
     */
    public static class BackgroundTask implements Runnable {
  
      private int id;
  
      public BackgroundTask(int id) {
        this.id = id;
      }
  
      /**
       * Sleep for a given amount of time to simulate loading.
       */
      @Override
      public void run() {
  
        try {
  
          System.out.println("Start #" + id + ": " + Thread.currentThread());
  
          long sleepTime = 2000; 
          Thread.sleep( sleepTime);
  
        } catch (InterruptedException e) {
          e.printStackTrace();
        } finally {
          System.out.println("Finish #" + id + ": " + Thread.currentThread());
        }
  
      }
    }
  
    /**
     * CompletableFuture which simulates loading and showing data.
     * @param taskId Identifier of the current task
     */
    public static void loadInBackground( int taskId) {
  
      // create the loading task
      BackgroundTask backgroundTask = new BackgroundTask( taskId);
  
      // "load" the data asynchronously
      CompletableFuture&lt;String&gt; completableFuture = CompletableFuture.supplyAsync(new Supplier&lt;String&gt;() {
  
        @Override
        public String get() {
  
          CompletableFuture&lt;Void&gt; future = CompletableFuture.runAsync(backgroundTask);
  
          try {
  
            future.get();
  
          } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
          }
  
          return "task " + backgroundTask.id;
        }
      });
  
      // display the data after they are loaded
      CompletableFuture&lt;Void&gt; future = completableFuture.thenAccept(x -&gt; {
  
        System.out.println( "Background task finished:" + x);
  
      });
  
    }
  
  
    public static void main(String[] args) {
  
      // runnable which invokes the background loader every second
      Runnable trigger = new Runnable() {
  
        int taskId = 0;
  
        public void run() { 
  
          loadInBackground( taskId++);
  
        }
      };
  
      // create scheduler
      ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
      ScheduledFuture&lt;?&gt; beeperHandle = scheduler.scheduleAtFixedRate(trigger, 0, 1, TimeUnit.SECONDS);
  
      // cancel the scheudler and the application after 10 seconds
      scheduler.schedule(() -&gt; beeperHandle.cancel(true), 10, TimeUnit.SECONDS);
  
      try {
        beeperHandle.get();
      } catch (Throwable th) {
      }
  
      System.out.println( "Cancelled");
      System.exit(0);
    }
  
  }
  </code></pre>
  
  <p>The output is this:</p>
  
  <pre><code>Start #0: Thread[ForkJoinPool.commonPool-worker-2,5,main]
  Start #1: Thread[ForkJoinPool.commonPool-worker-4,5,main]
  Start #2: Thread[ForkJoinPool.commonPool-worker-6,5,main]
  Finish #0: Thread[ForkJoinPool.commonPool-worker-2,5,main]
  Background task finished:task 0
  Finish #1: Thread[ForkJoinPool.commonPool-worker-4,5,main]
  Background task finished:task 1
  Start #3: Thread[ForkJoinPool.commonPool-worker-4,5,main]
  Finish #2: Thread[ForkJoinPool.commonPool-worker-6,5,main]
  Background task finished:task 2
  Start #4: Thread[ForkJoinPool.commonPool-worker-6,5,main]
  Start #5: Thread[ForkJoinPool.commonPool-worker-2,5,main]
  Finish #3: Thread[ForkJoinPool.commonPool-worker-4,5,main]
  Background task finished:task 3
  Start #6: Thread[ForkJoinPool.commonPool-worker-4,5,main]
  Finish #4: Thread[ForkJoinPool.commonPool-worker-6,5,main]
  Background task finished:task 4
  Finish #5: Thread[ForkJoinPool.commonPool-worker-2,5,main]
  Background task finished:task 5
  Start #7: Thread[ForkJoinPool.commonPool-worker-2,5,main]
  Finish #6: Thread[ForkJoinPool.commonPool-worker-4,5,main]
  Start #8: Thread[ForkJoinPool.commonPool-worker-6,5,main]
  Background task finished:task 6
  Start #9: Thread[ForkJoinPool.commonPool-worker-4,5,main]
  Finish #7: Thread[ForkJoinPool.commonPool-worker-2,5,main]
  Background task finished:task 7
  Start #10: Thread[ForkJoinPool.commonPool-worker-2,5,main]
  Finish #8: Thread[ForkJoinPool.commonPool-worker-6,5,main]
  Background task finished:task 8
  Cancelled
  </code></pre>
  
  <p>The goal is to have e. g. #1 and #2 skipped because #0 is still running.</p>
  
  <p><strong><em>Problem</em></strong></p>
  
  <p>Where do you properly set the blocking mechanism? Should synchronization be used? Or some <code>AtomicBoolean</code>? And if so, should it be inside the <code>get()</code> method or elsewhere?</p>