Java并发基础实践:退出任务II2014-08-17 blogjava Sha Jiang在本系列的上一篇中所述的退出并发任务的方式都是基于JDK 5之前的API,本文将介绍使用由JDK 5引入的并发工具包中的API来退出任务。(2013.10.08最后更新)在本系列的前一篇中讲述了三种退出并发任务的方式--停止线程;可取消的任务;中断,但都是基于JDK 5之前的API。本篇将介绍由JDK 5引入的java.concurrent包中的Future来取消任务的执行。1. Future模式Future是并发编程中的一种常见设计模式,它相当于是Proxy模式与Thread-Per-Message模式的结合。即,每次都创建一个单独的线程去执行一个耗时的任务,并且创建一个Future对象去持有实际的任务对象,在将来需要的时候再去获取实际任务的执行结果。
依然先创建一个用于扫描文件的任务FileScannerTask,如代码清单1所示,
清单1public class FileScannerTask implements Runnable {private File root = null;private ArrayList<String> filePaths = new ArrayList<String>();public FileScannerTask(File root) {if (root == null || !root.exists() || !root.isDirectory()) {throw new IllegalArgumentException("root must be directory");}this.root = root;}@Overridepublic void run() {travleFiles(root);}private void travleFiles(File parent) {String filePath = parent.getAbsolutePath();filePaths.add(filePath);if (parent.isDirectory()) {File[] children = parent.listFiles();if (children != null) {for (File child : children) {travleFiles(child);}}}}public List<String> getFilePaths() {return (List<String>) filePaths.clone();}}此处的文件扫描任务,提供了一个getFilePaths()方法以允许随时都可以取出当前已扫描过的文件的路径(相当于一个任务快照)。然后,创建一个针对该任务的Future类,如代码清单2所示,
清单2public class FileScannerFuture {private FileScannerTask task = null;public FileScannerFuture(FileScannerTask task) {new Thread(task).start();this.task = task;}public List<String> getResult() {return task.getFilePaths();}}FileScannerFuture持有FileScannerTask的引用,并创建一个独立的线程来执行该任务。在任务的执行过程中,应用程序可以在"未来"的某个时刻去获取一个任务的快照,如代码清单3所示,
清单3public static void main(String[] args) throws Exception {FileScannerFuture future = new FileScannerFuture(new FileScannerTask(new File("C:")));TimeUnit.SECONDS.sleep(1);List<String> filePaths1 = future.getResult();System.out.println(filePaths1.size());TimeUnit.SECONDS.sleep(1);List<String> filePaths2 = future.getResult();System.out.println(filePaths2.size());}