title: Is there a way to persist state in a multi-threaded app in case of restart or abrupt shutdown
body: <p>In a program that tasks are taken from a one file and are executed in parallel i want my program to survive failures / restarts etc. and to resume its execution instead of starting from the beginning each time in case i have a very big list of tasks in the file. What is the proper way of achieving this goal i didn't find much in google to start from. My tasks representation in java are simple pojos with 3 "File" members. Here is my code so far. Thank you for any help in advance.</p>
  
  <pre><code>import java.io.*;
  import java.nio.file.*;
  import java.util.*;
  import java.util.concurrent.*;
  import java.util.concurrent.atomic.AtomicInteger;
  
  public class MyTaskManager {
      private static AtomicInteger id;
      private static String[] in;
      private static String cmd;
      private static Task task;
      private static Process process;
      private static MyTaskManager taskManager;
      private static Semaphore sem;
      private static Map&lt;String, Task&gt; taskMap;
      private static StringBuffer sb;
      private static List&lt;Runnable&gt; threadList;
  
  
      public static void main(String[] args) throws IOException {
          id = new AtomicInteger();
          taskManager = new MyTaskManager();
          threadList = new ArrayList&lt;&gt;();
          taskMap = new ConcurrentHashMap&lt;&gt;();
          sem = new Semaphore(1);
          for (int i = 0; i &lt; 2; i++) {
              Thread t = new Thread(new Runnable() {
                  @Override
                  public void run() {
                      try {
                          // Get task
                          synchronized (taskManager) {
                              String line = Files.readAllLines(Paths.get("commands.txt"))
                                      .get(id.get());
                              id.getAndIncrement();
                              in = line.split(" ");
                              cmd = createCmd(cmd);
                              task = new Task(cmd);
                          }
                          // Persist task for later execution if it has missing dependencies
                          if (!task.checkCondition(task)) {
                              sem.acquire();
                              taskMap.put(task.getFile_dep_1().toString().trim(), task);
                              taskMap.put(task.getFile_dep_2().toString().trim(), task);
                              sem.release();
                              // execute the task and see if persisted task can continue his execution
                          } else if (task.checkCondition(task)) {
                              sem.acquire();
                              process = Runtime.getRuntime()
                                      .exec("cmd /c start cmd.exe /k \"" + task.getCmd() + "\"");
                              process.waitFor();
                              String taskKey = task.getOutput_file().toString().trim();
                              System.out.println(taskKey);
                              if (taskMap.containsKey(taskKey)) {
                                  System.out.println("In contains key " +
                                          Thread.currentThread().getName());
                                  Task taskTmp = taskMap.get(taskKey);
                                  process = Runtime.getRuntime()
                                          .exec("cmd /c start cmd.exe /k \"" + taskTmp.getCmd() + "\"");
                                  process.waitFor();
                              }
                              sem.release();
                          }
  
                      } catch (IOException | InterruptedException e) {
                          Thread.currentThread().interrupt();
                          e.printStackTrace();
                      }
                  }
              });
              threadList.add(t);
          }
  
          BlockingQueue&lt;Runnable&gt; worksQueue = new
                  ArrayBlockingQueue&lt;&gt;(10);
          RejectedExecutionHandler rejectionHandler = new
                  RejectedExecutionHandlerImpl();
          ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 2, 20,
                  TimeUnit.SECONDS, worksQueue, rejectionHandler);
          executor.prestartAllCoreThreads();
  
          worksQueue.add(new MultiRunnable(threadList));
  
          executor.shutdown();
      }
  
  
      private static String createCmd(String cmd) {
          StringJoiner stringJoiner = new StringJoiner(" ");
          stringJoiner.add(in[0]).add(in[1]).add(in[2])
                  .add(in[3]).add(in[4]);
          return stringJoiner.toString();
      }
  }
  
  </code></pre>
  
  <pre><code>class Task {
      private File file_dep_1;
      private File file_dep_2;
      private File output_file;
  
      .......
  }
  </code></pre>