Callable接口和Future接口

1.Callable和Future

Callable作用和Runnable类似,但是有返回值。对应Runnable接口的run方法,它有个call方法

V call()
       throws Exception

Future用于保存线程异步计算的结果,它最重要的方法是

V get()
      throws InterruptedException,
             ExecutionException

用于获取运算结果,它在调用时被阻塞,直到运算完成。可以被打断。

Future往往和Callable结合使用。

执行一个有返回值的任务步骤如下:

1.新建一个任务,实现Callable接口

2.用ExecutorService的submit方法提交任务

3.任务返回的计算结果是一个Future对象,调用Future对象的get获取结果

以下例子用线程池启动10个任务,并依次打印他们的返回值。

public class CallableDemo {

	public static void main(String[] args) {
		ExecutorService exec = Executors.newCachedThreadPool();
		ArrayList<Future<String>> results =
				new ArrayList<Future<String>>();
		for (int i = 0; i < 10; i++) {
			results.add(exec.submit(new TaskWithResult(i)));
		}
		for (Future<String> fs : results) {
			try {
				System.out.println(fs.get());
			} catch (InterruptedException | ExecutionException e) {
				e.printStackTrace();
			}
			finally {
				exec.shutdown();
			}
		}
	}
}

class TaskWithResult implements Callable<String> {
	private int id;
	
	public TaskWithResult(int id) {
		this.id = id;
	}

	//有返回结果的方法
	@Override
	public String call()  {
		return "result of TaskWithResult" + id;
	}
}
输出:

result of TaskWithResult0
result of TaskWithResult1
result of TaskWithResult2
result of TaskWithResult3
result of TaskWithResult4
result of TaskWithResult5
result of TaskWithResult6
result of TaskWithResult7
result of TaskWithResult8
result of TaskWithResult9


2.FutureTask包装器

FutureTask可以将Callable转换成Future和Runnable,它同时实现了2个的接口:

public class FutureTask<V> implements RunnableFuture<V> 

public interface RunnableFuture<V> extends Runnable, Future<V>

以下的例子实现了统计指定目录下包含关键字的文件数目,

它用FutureTask对象包装一个Callable,启动任务进行统计,任务的call方法中采用递归的方式,遇到目录则再次启动一个线程,传入FutureTask包装的任务,获取运行的Future对象。如果遇到的是单个文件,则对文件进行统计。最后将所有统计结果(对于单个文件的count和目录的future list中的每个count)相加。

虽然get方法是阻塞的,但是在递归中启动了多个线程,其实他们是同时工作的,所以执行速度不会很慢。

public class FutureTest {

	public static void main(String[] args) throws Exception {
		Scanner in = new Scanner(System.in);
		System.out.print("输入目录:");
		String directory = in.nextLine();
		System.out.print("输入关键词:");
		String keyword = in.nextLine();
		
		MatchCounter counter = new MatchCounter(new File(directory), keyword);
		FutureTask<Integer> task = new FutureTask<Integer>(counter);
		ExecutorService executor = Executors.newSingleThreadExecutor();
		executor.execute(task);
		System.out.println("一共有"+ task.get() +"个匹配的文件");

	}
}

class MatchCounter implements Callable<Integer> {

	private File directory;
	private String keyword;
	private int count;

	public MatchCounter(File directory, String keyword) {
		this.directory = directory;
		this.keyword = keyword;
	}
	
	@Override
	public Integer call() throws Exception {
		count = 0;
		try {
			File[] files = directory.listFiles();
			ArrayList<Future<Integer>> results =
					new ArrayList<Future<Integer>>();
			for (File file : files) {
				if (file.isDirectory()) {
					MatchCounter counter = new MatchCounter(file, keyword);
					FutureTask<Integer> task = 
							new FutureTask<Integer>(counter);
					results.add(task);
					ExecutorService executor = Executors.newSingleThreadExecutor();
					executor.execute(task);
				} else {
					if (search(file)) {
						count++;
					}
				}
			}
			
			for (Future<Integer> result : results) {
				try {
					count += result.get();
				} catch (Exception e) {
				}
			}
		} catch (Exception e) {
		}
		return count;
	}
	
	public boolean search(File file) {
		try {
			Scanner inScanner = new Scanner(new FileInputStream(file));
			boolean found = false;
			while (!found && inScanner.hasNextLine()) {
				String line = inScanner.nextLine();
				if (line.contains(keyword)) {
					found = true;
				}
			}
			inScanner.close();
			return found;
		}catch (IOException e){
			return false;
		}
	}	
}
运行结果:

输入目录:F:/log
输入关键词:a
一共有1个匹配的文件

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值