JAvaのRunnable,Callable,Future,Futuretaskの違いと使い方

9562 ワード

JAvaマルチスレッドがタスクを実行するとき、これらのインタフェースとクラスはよく使用されます.次に、ソースコードを見て、彼らの違いと使い方を見てみましょう.
Runnable
@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface Runnable is used
     * to create a thread, starting the thread causes the object's
     * run method to be called in that separately executing
     * thread.
     * 

* The general contract of the method run is that it may * take any action whatsoever. * * @see java.lang.Thread#run() */ public abstract void run(); }


Callable
@FunctionalInterface
public interface Callable {
    /**
     * 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 {

    /**
     * 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.
     *
     * 

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 implements RunnableFuture 
public interface RunnableFuture extends Runnable, Future {
    /**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     */
    void run();
}
ExecutorServiceスレッドプールの3つの実行スレッドメソッド
Future submit(Callable task);
Future submit(Runnable task, T result);
Future> submit(Runnable task);
最初のsubmitメソッドのパラメータタイプはCallableです.
2つ目の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 future1 = executor.submit(task);
		GetTotalTask task1 = new GetTotalTask();
		Future future2 = executor.submit(task1);
		boolean canceled = false;
		// canceled = future2.cancel(true);
		SendMessageTask task3 = new SendMessageTask();
		Future 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 futureTask1 = new FutureTask(task1);
		executor.submit(futureTask1);
		GetTotalTask task2 = new GetTotalTask();
		FutureTask futureTask2 = new FutureTask(task2);
		boolean canceled = false;
		// canceled = futureTask1.cancel(true);
		executor.submit(futureTask2);

		SendMessageTask task3 = new SendMessageTask();
		FutureTask futureTask3 = new FutureTask(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 {
		@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 {
		@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 {

		@Override
		public Integer call() throws Exception {
			System.out.println("   3,    ,     ");
			Thread.sleep(6000);
			System.out.println("   3,    !");
			return 1;
		}

	}
}