Java并发编程实践之Callable,Future,RutureTask的使用

一般使用线程有两种方式:继承Thread类重写run方法;另一种就是实现Runnable接口,实现run方法。但是run方法没有返回值,假如我们在使用线程的时候想要知道运行结果,就只能使用重写run方法,并且使用回调来得到运行结果。但是我们Callable接口的call方法,可以返回执行结果。如下:

public interface Runnable
{

    public abstract void run();
}
public interface Callable
{

    public abstract Object call()
        throws Exception;
}
Future 表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用 get 方法来获取结果,如有必要,计算完成前可以阻塞此方法。取消则由 cancel 方法来执行。还提供了其他方法,以确定任务是正常完成还是被取消了。一旦计算完成,就不能再取消计算。如果为了可取消性而使用 Future 但又不提供可用的结果,则可以声明 Future<?> 形式类型、并返回 null 作为底层任务的结果。

 public abstract boolean <code><strong><a target=_blank href="">cancel</a></strong>(boolean mayInterruptIfRunning)</code> ;
cancel用来取消任务,取消成功返回true,取消失败返回false。mayInterruptIfRunning表示正在执行但还没执行完的任务是否可以取消。如果任务已完成、或已取消。那么不管mayInterruptIfRunning是ture还是false,方法执行返回false。如果任务在执行中,那么若mayInterruptIfRunning为ture那么返回true;若mayInterruptIfRunning为false,结果返回false。如果任务还没执行,不管mayInterruptIfRunning是ture还是false,方法返回true。

 public abstract Object get()
        throws InterruptedException, ExecutionException;
get方法用来获取线程执行返回结果。这个方法回阻塞,知道返回结果。
   public abstract boolean isCancelled();
 如果在任务正常完成前将其取消,则返回 true。
get(long timeout, TimeUnit unit) 
  如有必要,最多等待为使计算完成所给定的时间之后,获取其结果(如果结果可用)。
public abstract boolean isDone();
  如果任务已完成,则返回 true

FutureTask:可取消的异步计算。利用开始和取消计算的方法、查询计算是否完成的方法和获取计算结果的方法,此类提供了对 Future 的基本实现。仅在计算完成时才能获取结果;如果计算尚未完成,则阻塞 get 方法。一旦计算完成,就不能再重新开始或取消计算。 
Callable:Callable 接口类似于 Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。但是 Runnable 不会返回结果,并且无法抛出经过检查的异常。 Callable 接口只有一个call方法,如下:

    public abstract Object call()
        throws Exception;
因为Executor接口只提供了一个方法,参数中只能接受Runnable类型,如下:

    public abstract void execute(Runnable runnable);
因此,Callable只能与ExecutorService一起使用。因为ExecutorService提供了可接受Callable类型的参数。如下:
   public abstract Future submit(Callable callable);

    public abstract Future submit(Runnable runnable, Object obj);

    public abstract Future submit(Runnable runnable);

下面来看使用示例:
示例1:使用Callable和Future,并且输出线程计算返回值

public class Test3 {
	
	public static void main(String[] args) {
		
		ExecutorService executor=Executors.newCachedThreadPool();
		
		Future<Integer> future=executor.submit(new Callable<Integer>() {
			@Override
			public Integer call() throws Exception {
				int sum=0;
				for (int i = 1; i <= 1000; i++) {
					sum+=i;
				}
				
				return sum;
			}
		});
		
		try {
			System.out.println("线程执行结果:"+future.get());
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
输出结果:

线程执行结果:500500

示例2:使用Callable和FutureTask,并且输出线程计算返回值

public class CallableFutureTask {
	
	public static void main(String[] args) {
		
		ExecutorService executor=Executors.newCachedThreadPool();
		
		FutureTask<Integer> futureTask=new FutureTask<Integer>(new Callable<Integer>() {
			@Override
			public Integer call() throws Exception {
				int sum=0;
				for (int i = 1; i <= 1000; i++) {
					sum+=i;
				}
				
				return sum;
			}
		});
		
		executor.submit(futureTask);
		
		executor.shutdown();
		
		try {
			System.out.println("线程执行结果:"+futureTask.get());
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
示例3:使用使用Callable和FutureTask,并且输出线程计算返回值。用启动普通线程来执行
public class CallableFutureTaskThread {
	
	public static void main(String[] args) {
		
		FutureTask<Integer> futureTask=new FutureTask<Integer>(new Callable<Integer>() {
			@Override
			public Integer call() throws Exception {
				int sum=0;
				for (int i = 1; i <= 1000; i++) {
					sum+=i;
				}
				
				return sum;
			}
		});
		
		Thread thread=new Thread(futureTask);
		thread.start();
		
		try {
			System.out.println("线程执行结果:"+futureTask.get());
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}









發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章