java之Runnable,Callable,Future,Futuretask区别与用法

java多线程执行任务的时候,这些接口和类是经常使用的,下面来看源码,看看他们之间的差别与用法。

Runnable

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

Callable

@FunctionalInterface
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


package java.util.concurrent;


public interface Future<V> {

    /**
     * Attempts to cancel execution of this task.  This attempt will
     * fail if the task has already completed, has already been cancelled,
     * or could not be cancelled for some other reason. If successful,
     * and this task has not started when {@code cancel} is called,
     * this task should never run.  If the task has already started,
     * then the {@code mayInterruptIfRunning} parameter determines
     * whether the thread executing this task should be interrupted in
     * an attempt to stop the task.
     *
     * <p>After this method returns, subsequent calls to {@link #isDone} will
     * always return {@code true}.  Subsequent calls to {@link #isCancelled}
     * will always return {@code true} if this method returned {@code true}.
     *
     * @param mayInterruptIfRunning {@code true} if the thread executing this
     * task should be interrupted; otherwise, in-progress tasks are allowed
     * to complete
     * @return {@code false} if the task could not be cancelled,
     * typically because it has already completed normally;
     * {@code true} otherwise
     */
    boolean cancel(boolean mayInterruptIfRunning);

    /**
     * Returns {@code true} if this task was cancelled before it completed
     * normally.
     *
     * @return {@code true} if this task was cancelled before it completed
     */
    boolean isCancelled();

    /**
     * Returns {@code true} if this task completed.
     *
     * Completion may be due to normal termination, an exception, or
     * cancellation -- in all of these cases, this method will return
     * {@code true}.
     *
     * @return {@code true} if this task completed
     */
    boolean isDone();

    /**
     * Waits if necessary for the computation to complete, and then
     * retrieves its result.
     *
     * @return the computed result
     * @throws CancellationException if the computation was cancelled
     * @throws ExecutionException if the computation threw an
     * exception
     * @throws InterruptedException if the current thread was interrupted
     * while waiting
     */
    V get() throws InterruptedException, ExecutionException;

    /**
     * Waits if necessary for at most the given time for the computation
     * to complete, and then retrieves its result, if available.
     *
     * @param timeout the maximum time to wait
     * @param unit the time unit of the timeout argument
     * @return the computed result
     * @throws CancellationException if the computation was cancelled
     * @throws ExecutionException if the computation threw an
     * exception
     * @throws InterruptedException if the current thread was interrupted
     * while waiting
     * @throws TimeoutException if the wait timed out
     */
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

Futuretask

public class FutureTask<V> implements RunnableFuture<V> 
public interface RunnableFuture<V> extends Runnable, Future<V> {
    /**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     */
    void run();
}
ExecutorService线程池的3个执行线程方法
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
第一个submit方法里面的参数类型就是Callable。

第二个submit方法里面的参数类型就是Runnable。


总结一下,Callable线程执行完之后可以有返回值,而Runnable无返回值。

而Futuretask是接口Future的实现类。ExecutorService.submit()的时候,返回就是Future,另外发现如果几个线程同时执行的时候,全部线程都执行完,总共耗时多少?这个需要获取每个线程的返回结果的时候,即future.get()的时候,才能正确计算出所有线程执行完所花费的时间,否则无法统计所有线程全部执行完成需要消耗多长的时间。在每个线程都调用future.get()后,会发现全部线程执行完成,其实所花费都全部时间等于耗时最长的那个线程,因为全部线程是并行执行的,下面给出Demo,大家可以运行一下体会消耗总时间的问题。

/**
 * 
 */
package com.figo.study.test;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

/**
 * 测试future和futuretask
 * @author figo
 *
 */
public class TestFutureTask {
	public static void main(String[] args) {
		useFuture();
		//useFutureTask();
	}

	public static void useFuture() {
		long start = System.currentTimeMillis();
		//不固定个数
		//ExecutorService executor = Executors.newCachedThreadPool();
		//固定线程池线程个数
		ExecutorService executor = Executors.newFixedThreadPool(12);
		GetPersonInfoTask task = new GetPersonInfoTask();
		Future<String> future1 = executor.submit(task);
		GetTotalTask task1 = new GetTotalTask();
		Future<Integer> future2 = executor.submit(task1);
		boolean canceled = false;
		// canceled = future2.cancel(true);
		SendMessageTask task3 = new SendMessageTask();
		Future<Integer> future3 = executor.submit(task3);
		// Thread thread=new Thread(task3);
		// thread.start();

		executor.shutdown();

		try {
			Thread.sleep(1000);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}

		System.out.println("主线程在执行任务");

		try {
			String result1 = "";
			int result2 = 0;
            int result3=0;
			result1 = future1.get();
			if (!canceled) {
				result2 = future2.get();
			}
            //如果这里不执行get操作,会发现总耗时是5秒,虽然线程3耗时6秒
			result3 = future3.get();
			System.out.println("线程1运行结果:" + result1 +",线程2运行结果:"+ result2+",线程3运行结果:"+result3);		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		long end = System.currentTimeMillis();
		System.out.println("所有任务执行完毕,耗时(秒):" + ((end - start) / 1000));
	}

	public static void useFutureTask() {
		// 第一种方式
		long start = System.currentTimeMillis();
		//不固定个数
		//ExecutorService executor = Executors.newCachedThreadPool();
		//固定线程池线程个数
		ExecutorService executor = Executors.newFixedThreadPool(12);
		GetPersonInfoTask task1 = new GetPersonInfoTask();
		FutureTask<String> futureTask1 = new FutureTask<String>(task1);
		executor.submit(futureTask1);
		GetTotalTask task2 = new GetTotalTask();
		FutureTask<Integer> futureTask2 = new FutureTask<Integer>(task2);
		boolean canceled = false;
		// canceled = futureTask1.cancel(true);
		executor.submit(futureTask2);

		SendMessageTask task3 = new SendMessageTask();
		FutureTask<Integer> futureTask3 = new FutureTask<Integer>(task3);
		executor.submit(futureTask3);
		
		executor.shutdown();

		try {
			Thread.sleep(1000);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}

		System.out.println("主线程在执行任务");
		try {
			String result1 = "";
			int result2 = 0;
            int result3=0;
			result1 = futureTask1.get();

			if (!canceled) {
				result2 = futureTask2.get();
			}
			 //如果这里不执行get操作,会发现总耗时是5秒,虽然线程3耗时6秒
			result3 = futureTask3.get();
			System.out.println("线程1运行结果:" + result1 +",线程2运行结果:"+ result2+",线程3运行结果:"+result3);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		long end = System.currentTimeMillis();
		System.out.println("所有任务执行完毕,耗时(秒):" + ((end - start) / 1000));
	}

	public static class GetPersonInfoTask implements Callable<String> {
		@Override
		public String call() throws Exception {
			System.out.println("子线程1,获取学生信息,在进行计算");
			Thread.sleep(5000);
			System.out.println("子线程1,执行完成!");

			return "姓名:abc,性别:f,地址:shanghai";
		}
	}

	public static class GetTotalTask implements Callable<Integer> {
		@Override
		public Integer call() throws Exception {
			System.out.println("子线程2,获取高考总分,在进行计算");
			Thread.sleep(3000);
			System.out.println("子线程2,执行完成!");
			return 650;
		}
	}

//	public static class SendMessageTask implements Runnable {
//		@Override
//		public void run() {
//			try {
//				System.out.println("子线程3,发送消息,在进行计算");
//				Thread.sleep(6000);
//				System.out.println("子线程3,执行完成!");
//			} catch (InterruptedException e) {
//				e.printStackTrace();
//			}
//		}
//	}

	public static class SendMessageTask implements Callable<Integer> {

		@Override
		public Integer call() throws Exception {
			System.out.println("子线程3,发送消息,在进行计算");
			Thread.sleep(6000);
			System.out.println("子线程3,执行完成!");
			return 1;
		}

	}
}




猜你喜欢

转载自blog.csdn.net/figo0423/article/details/80561585
今日推荐