【开发百宝箱系列】- FutrueTask 使用

/**
* 当一个线程需要等待另一个线程把某个任务执行完后它才能继续执行,此时可以使用FutureTask。
* 假设有多个线程执行若干任务,每个任务最多只能被执行一次。
* 当多个线程试图同时执行同一个任务时,只允许一个线程执行任务,其他线程需要等待这个任务执行完后才能继续执行
*
* @author gerry pang
* @since 2020年10月21日 下午4:33:09
*/
public class FutureTaskDemo {

      private final Map<String, Future<String>> taskCache = new  ConcurrentHashMap<>();
      public String executeTask(String taskName) {
            Future<String> future = taskCache.get(taskName);
            if (future == null) {
                  Callable<String> task = new Callable<String>() {
                        @Override
                        public String call() throws Exception {
                              System.out.println("==> start  taskName:"+taskName);
                              Thread.sleep(new Random().nextInt(1000));
                              System.out.println("==> end  taskName:"+taskName);
                              return taskName;
                        }
                  };

                  FutureTask<String> futureTask = new  FutureTask<String>(task);
                  future = taskCache.putIfAbsent(taskName, futureTask);
                  if (future == null) {
                        future = futureTask;
                        futureTask.run();
                  }
            }
            try {
                  return future.get();
            } catch (InterruptedException e) {
                  e.printStackTrace();
            } catch (ExecutionException e) {
                  e.printStackTrace();
            }
            return taskName;
      }

      public static void main(String[] args) {
            FutureTaskDemo futureTaskDemo = new FutureTaskDemo();
            futureTaskDemo.executeTask("123");
            futureTaskDemo.executeTask("123");
            futureTaskDemo.executeTask("456");
            futureTaskDemo.executeTask("456");
            futureTaskDemo.executeTask("000");
            futureTaskDemo.executeTask("123");
      }
}

执行结果

==> start taskName:123
==> end taskName:123
123
123
==> start taskName:456
==> end taskName:456
456
456
==> start taskName:000
==> end taskName:000
000
123

参考资料

  • 《并发编程的艺术》 10.4.2 FutrueTask的使用

发表评论