Java的多线程之Callable与Future

一、Callable与Future

       Runnable封装了一个异步运行的任务,可以把它想象成为一个没有参数和返回值的异步方法。Callable与Runnable类似,但是有返回值。Callable接口是一个参数化的类型,只有一个方法call。

public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

       类型参数是返回值的类型。

       Future保存异步计算的结果。可以启动一个计算,将Future对象交给某个线程,然后忘掉它。Future对象的所有者在结果计算好之后就可以获得它。

       Future接口具有下面方法:

public interface Future<V> {

    boolean cancel(boolean mayInterruptIfRunning);

    boolean isCancelled();

    boolean isDone();

    V get() throws InterruptedException, ExecutionException;

    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

       第一个get方法的调用被阻塞,直到计算完成。如果在计算完成之前,第二个方法的调用超时,抛出一个TimeoutException异常。如果运行该计算的线程被中断,两个方法都将抛出InterruptedException。如果计算已经完成,那么get方法立即返回。

       如果计算还在进行,isDone方法返回false;如果完成了,则返回true。

       可以用cancel方法取消该计算。如果计算还没有开始,它被取消且不再开始。如果计算处于运行之中,那么如果mayInterrupt参数为true,它被中断。

       FutureTask包装器是一种非常便利的机制,可将Callable转换成Future和Runnable,它同时实现两者的接口。

例如:

Callable<Integer> myComputation = ...;
FutureTask<Integer> task = new FutureTask<>(myComputation);
Thread t = new Thread(task); //it's a Runnable
t.start();
...
Integer result = task.get(); //it's a Future

       每一次对get的调用都会发生阻塞直到结果可获得为止。当然,线程时并行运行的,因此,很可能在大致相同的时刻所有的结果都可获得。

实例如下:

package com.thread.callable;

import java.io.File;
import java.util.Scanner;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class FutureTest {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		System.out.println("请输入目录:");
		String directory = in.nextLine();
		System.out.println("请输入关键字:");
		String keyword = in.nextLine();

		MatchCounter counter = new MatchCounter(new File(directory), keyword);
		FutureTask<Integer> task = new FutureTask<>(counter);
		Thread t = new Thread(task);
		t.start();
		try {
			System.out.println(task.get()+" matching files.");
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}
		in.close();

	}

}
package com.thread.callable;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

public 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() {
		count = 0;
		try {
			File[] files = directory.listFiles();
			List<Future<Integer>> results = new ArrayList<>();

			for (File file : files) {
				if (file.isDirectory()) {
					MatchCounter counter = new MatchCounter(file, keyword);
					FutureTask<Integer> task = new FutureTask<>(counter);
					results.add(task);
					Thread t = new Thread(task);
					t.start();
				} else {
					if (search(file))
						count++;
				}
			}
			for (Future<Integer> result : results) {
				try {
					count += result.get();
				} catch (ExecutionException e) {
					e.printStackTrace();
				}
			}
		} catch (InterruptedException e) {
		}
		return count;

	}

	public boolean search(File file) {
		try (Scanner in = new Scanner(file)) {
			boolean found = false;
			while (!found && in.hasNext()) {
				String line = in.nextLine();
				if (line.contains(keyword))
					return found = true;
			}
			return found;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return false;
		}
	}
}

常用方法:  V call()  运行一个将产生结果的任务

                   V get() 

                   V get(long time,TimeUnit unit)  获取结果,如果没有结果可用,则阻塞直到真正得到结果超过指定时间为止。如果不成功,第二个方法会抛出TimeoutException异常。

                   FutureTask(Callable<V> task) 

                   FutureTask(Runnable task,V result) 构造一个既是Funture<V>又是Runnable的对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值