java學習——線程

第一種:extend Threadjava

第二種:implement Runnable多線程

第三種:Executors.newFixedThreadPool(int n).execute(...)測試

第一種(繼承)、第二種(實現接口)是所有版本jdk一直支持,第三種(線程池)jdk1.5纔開始出現。this


/*第一種
1.自定義類繼承Thread
2.自定義類複寫run方法
3.實例化自定義類,調用start方法(做用是啓動線程並調用複寫的run方法)
*/

class Demo extend Thread{
    public void run(){...}
}
class T{
    public static void main(String[] args){
        new Demo().start();   //線程1
        new Demo().start();   //線程2
        new Demo().start();   //線程3
    }
}
/*第二種【經常使用】
1.自定義類實現Runnable接口
2.自定義類複寫run方法
3.實例化自定義類,把自定義類的實例做爲參數實例化Thread類(可實例化多個,就是所謂的多線程),而後調用start方法
*/

class Demo implement Runnable{
    public void run(){...}
}
class T{
    public static void main(String[] args){
        Demo demo = new Demo();
        new Thead(demo).start();   //線程1
        new Thead(demo).start();   //線程2
        new Thead(demo).start();   //線程3
    }
}

第一種和第二種方法其實同樣,主要是由於java的單繼承機制纔出現了第二種【經常使用】方法。線程

//第三種
//簡易版
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test{
    public static void main(String[] args){
        ExecutorService pool = Executors.newFixedThreadPool(3);   //建立線程池,容量爲3
                for(int i=0;i<10;i++)
                {
                    pool.execute(new Runnable(){public void run(){ System.out.println();}});
                }
                Executors.newCachedThreadPool().execute(new Runnable(){public void run(){}});
                Executors.newSingleThreadExecutor().execute(new Runnable(){public void run(){}});
    }
}

//詳細版(可運行進行測試)
import java.util.concurrent.*;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;

public class Test {
	public static void main(String[] args) throws ExecutionException,
	    InterruptedException {
	   System.out.println("----程序開始運行----");
	   Date date1 = new Date();

	   int taskSize = 5;
	   // 建立一個可重用固定線程數的線程池,以共享的無界隊列方式來運行這些線程。
	   ExecutorService pool = Executors.newFixedThreadPool(taskSize);
	   // 用於存聽任務返回值
	   List<Future> list = new ArrayList<Future>();
	   for (int i = 0; i < taskSize; i++) {
	    Callable c = new MyCallable(i + " ");
	    // 執行任務並獲取Future對象
	    //pool提交一個返回值的任務用於執行,返回一個表示任務的未決結果的Future。
	    Future f = pool.submit(c);
	    // System.out.println(">>>" + f.get().toString());
	    list.add(f);
	   }
	   // 關閉線程池
	   pool.shutdown();

	   // 遍歷全部線程的返回值
	   for (Future f : list) {
	    System.out.println(">>>" + f.get().toString());
	   }

	   Date date2 = new Date();
	   System.out.println("----程序結束運行----,程序運行時間【"
	     + (date2.getTime() - date1.getTime()) + "毫秒】");
	}
}

//有返回值實現Callable,無返回值實現Runnable
class MyCallable implements Callable<Object> {
	private String taskNum;

	MyCallable(String taskNum) {
	   this.taskNum = taskNum;
	}
	//實現Callable必須實現call方法
	//計算結果,若是沒法計算結果,則拋出一個異常。
	public Object call() throws Exception {
	   System.out.println(">>>" + taskNum + "任務啓動");
	   Date dateTmp1 = new Date();
	   Thread.sleep(1000);
	   Date dateTmp2 = new Date();
	   long time = dateTmp2.getTime() - dateTmp1.getTime();
	   System.out.println(">>>" + taskNum + "任務終止");
	   return taskNum + "任務返回運行結果,當前任務時間【" + time + "毫秒】";
	}
}

    個人理解:code

    由Executors.newFixedThreadPool(int n)定義一個能夠執行必定數量線程的線程池,pool.submit(c)把須要執行的任務扔進(提交到)線程池進行執行,這樣就能夠不阻塞得同時執行多個任務(即所謂的多線程)。對象

    Callable和Runnable同樣是接口,二者的區別是Callable執行完call()後返回一個Object,Runnable執行完run()後不返回。call()和run()功能相同(除了有無返回值的區別)。繼承

    Future是一個類型(也就是類啦),用來裝Callable執行完call()後返回的Object(其實這裏返回的是Object,爲啥不能用Object來裝,非要用Future來裝呢?我也不明白,可是API說須要用這個裝就用唄)。接口

    因爲是多線程,每一個線程都執行完都有返回,因此須要用一個容器(即集合)——ArrayList<Future>來裝。隊列

    線程池的方法能夠獲取任務執行的返回值(這些返回值可能有用),另外,此方法也能夠執行submit(T<? implement Runnable>)無返回值的方法。

    so,我以爲第三種通吃,直接用第三種方式得了。

相關文章
相關標籤/搜索