Java多線程之Callable、Future、FutureTask

package Thread;

import java.util.Scanner;
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;

/**
 * 使用Thread和Runable都可以創建線程,但是都沒有返回值。JDK1.5之後,java 推出了 Callable,使用帶有泛型參數
 * 的Callable對象,可以返回線程執行後的結果。大多數情況下,Callable配合ExecutorService使用。或者
 * 、
 * Callable,FutureTask,ExecutorService三者一起使用。
 * 
 * 
 * 
 * 
 * ExecutorService的submit方法有三種重載形式,分別爲:
 *  1.<T> Future<T> submit(Callable<T> c);
 *  2.<T> Future<T> submit(Runnable r,T Result);
 *  3.Future<?> submit(Runnable r);
 *  其中,第一種和第三種重載方法使用最多。
 *  
 *  FutureTask是Runnable和Callable的子類,所以ExecutorService的submit方法的參數可以直接是
 *  FutureTask對象。
 *  FutureTask有兩個構造方法,一個是 FutureTask(Callable<V> callable),
 *  另一個是 FutureTask(Runnable runnable, V result),其中result是創建FutureTask時設置的,
 * 
 */

/**
 * FutureTask 繼承於Runnable和uture。因此 ExecutorService的submit中可以使用FutureTask作爲參數
 */
public class FutureRunnableTest {

	 static ExecutorService executorService = Executors.newCachedThreadPool();
	
	public static void main(String[] args) {
		f4();
	}
	
	// ExecutorService+Future +Callable
	static void f1(){
		Future<Integer> future=executorService.submit(new MyCallable());
		
		/**
		 * 調用shutdown方法關閉線程池,調用shutdown方法之後所有線程執行結束後線程池關閉。
		 * 所以在使用線程池的時候如果是方法內部使用一定要shutdown銷燬線程,如果是全局使用的靜態線程池可以不shutdown
		 * 
		 * 而shutdownNow會強行關閉線程池,正在執行的線程也會被嘗試銷燬。
		 * awaitTermination方法一般在shutdown訪法之後,阻塞直到線程池中所有任務執行結束。
		 */
		executorService.shutdown();
		
		try {
			System.err.println("future獲取到的值爲:"+future.get());
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
	
	
	//ExecutorService+FutureTask+Callable
	static void f2(){
		
		MyCallable myCallable=new MyCallable();
		FutureTask<Integer> futureTask=new FutureTask<Integer>(myCallable);
		executorService.submit(futureTask);
		executorService.shutdown();
		try {
			System.err.println("futureTask獲取到的值爲:"+futureTask.get());
			System.err.println("futureTask執行是否結束:"+futureTask.isDone());
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
	
	//ExecutorService+FutureTask+Runnable(感覺沒太大意義)
	static void f3(){
		MyRunable myRunable=new MyRunable();
		//使用Runable作爲FutureTask的參數時,需設置result的值(似乎沒太大意義)
		FutureTask<Integer> futureTask=new FutureTask<Integer>(myRunable,55);
		executorService.submit(futureTask);
		executorService.shutdown();
		
		try {
			//執行結果:futureTask執行是否結束:false
			System.err.println("futureTask執行是否結束:"+futureTask.isDone());
			//執行結果futureTask獲取到的值爲:55
			System.err.println("futureTask獲取到的值爲:"+futureTask.get());
		} catch (Exception e) {
			e.printStackTrace();
		} 
		
	}
	
	//Thread+FutureTask+Callable(Runable)
	//因爲FutureTask是Runable的實現類,可以直接使用Thread構建線程程
	static void f4(){
		MyCallable myCallable=new MyCallable();
		FutureTask<Integer> futureTask=new FutureTask<Integer>(myCallable);
		/**
		 * 或者使用Runnable構建FutureTask者
		 * MyRunable myRunable=new MyRunable();
		   FutureTask<Integer> futureTask=new FutureTask<Integer>(myRunable,55);
		 */

		Thread thread=new Thread(futureTask);
		thread.start();
		
		try {
			System.err.println("futureTask獲取到的值爲:"+futureTask.get());
			System.err.println("futureTask執行是否結束:"+futureTask.isDone());
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}

}

  class MyCallable implements Callable<Integer>{


	public Integer call() throws Exception {
		int sum=0;
		int num=1000;
		for(int i=0;i<=num;i++){
			sum=sum+i;
		}
		
		return sum;
	}}
  
  class MyRunable implements Runnable{

	@Override
	public void run() {
		try {
			Thread.sleep(200);
			
			System.err.println(Thread.currentThread().getName()+" 線程執行結束");
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	  
  }

參考連接:https://blog.csdn.net/predisw/article/details/49094177,感謝作者分享!

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