title: How do I get results from my work queue task?
body: <p>I've implemented a simply work queue that receives tasks from a number of different threads. I want these tasks to return a value to their source thread, but can't figure out how to do that.
  I've considered using a future, but there's no way to explicitly set the future's value. I could use a property, but I don't believe those are thread safe.</p>
  
  <p>Every task is an implementation of DBRequest. The actual content varies, but the result of all activities is a string.
  An asynchronous thread creates a DBRequest and submits it to the queue. The queue runs the task, which produces a string. How do I get that string back to the thread that created the DBRequest, and how can I cause my creator thread to wait for the result?</p>
  
  <pre><code>public interface DBRequest {
      String execute(VdtsSysDB vdtsSysDB, BoardLoad currentLoad);
  }
  
  public class DBQueue implements Runnable {
      private static DBQueue dbQueue;
      private LinkedBlockingQueue&lt;DBRequest&gt; queue = new LinkedBlockingQueue&lt;&gt;();
      private VdtsSysDB vdtsSysDB = new VdtsSysDB();
      private ReentrantLock lock = new ReentrantLock();
      private static final Logger LOG = LoggerFactory.getLogger(DBQueue.class);
      private boolean kill = false;
  
      private BoardLoad currentLoad;
      private ProgressController progressController;
  
      public static DBQueue getInstance() {
          if (dbQueue == null) synchronized (DBQueue.class) {
              if (dbQueue == null)
                  dbQueue = new DBQueue();
          }
          return dbQueue;
      }
  
      private DBQueue() {
      }
  
      public ReentrantLock getLock() {
          return lock;
      }
  
      @Override
      public void run() {
          LOG.info("Starting DBQueue loop. Kill {}.", kill);
          while (!kill) {
              DBRequest dbRequest = removeRequest();
              if (dbRequest != null) {
                  lock.lock();
                  String result = dbRequest.execute(vdtsSysDB, currentLoad);
                  lock.unlock();
                  if (progressController != null) Platform.runLater(() -&gt;
                          progressController.updateDisplay(currentLoad));
              }
          }
          vdtsSysDB.getEntityManager().close();
      }
  
  
      public void addRequest(DBRequest dbRequest) {
          try {
              queue.add(dbRequest);
              LOG.info("Added request.");
          } catch (Exception e) {
              LOG.error("Can't add element.", e);
          }
      }
  
      private DBRequest removeRequest() {
          DBRequest result = null;
          try {
              //result = queue.poll(10, TimeUnit.SECONDS);
              result = queue.take();
          } catch (Exception e) {
              LOG.error("Exception.", e);
          }
          return result;
      }
  
      public void killDBQueue() {
          kill = true;
          LOG.info("Shutting down DBQueue.");
      }
  
      public static void start() {
          Thread thread = new Thread(DBQueue.getInstance(), "DBQueue Thread");
          thread.start();
          LOG.info("Starting DBQueue.");
      }
  
      public BoardLoad getCurrentLoad() {
          if (currentLoad == null)
              currentLoad = BoardLoad.getLastOpenLoad(vdtsSysDB);
          return currentLoad;
      }
  
      public void setCurrentLoad(BoardLoad proposedLoad) {
          // We can only have one open load, and by definition, the current load is open. So close it.
          if (this.currentLoad != null &amp;&amp; !this.currentLoad.equals(proposedLoad)) {
              currentLoad.close(vdtsSysDB);
              if (proposedLoad != null) {
                  this.currentLoad = vdtsSysDB.getEntityManager().find(BoardLoad.class, proposedLoad.getId());
              } else this.currentLoad = null;
          }
      }
  
      public ProgressController getProgressController() {
          return progressController;
      }
  
      public void setProgressController(ProgressController progressController) {
          this.progressController = progressController;
      }
  }
  </code></pre>
  
  <p>EDIT: I'm using this queue to synchronize database access, reducing the need for locks and ensuring that requests are completed sequentially. I don't believe there is any other way to achieve this sort of asynchronous request -> synchronous request change.
  But I'd love to have that belief changed.</p>