java線程實現的三種方式

Java中使用Thread代表線程類,所有的線程類都必須是Thread類或者其子類的實例。每個線程的作用就是完成一定的任務,即執行一段程序流。Java中使用線程執行體來表示這段程序流。


Java中線程的實現方式有如下三種:


1.繼承Thread類
public class Thread extends Object implements Runnable
定義Thread類的子類,並重寫Thread類的run()方法,創建子類對象(即線程對象),調用線程對象的start()方法來啓動該線程。

/**
 * @Description:
 * @author WEISANGENG
 * @date 2017年3月3日
 */
public class ThreadDemo extends Thread {


private int i;


/**
* @功能描述: Thread線程的方式
*  
* @date 2017年3月3日
* @author WEISANGENG
*/
@Override
public void run() {
for (; i < 100; i++) {
System.out.println(getName() + " " + i);
}
}


public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
// currentThread是Thread類的靜態方法,該方法返回當前正在執行的線程對象
// getName()返回當前線程對象的名字
System.out.println(Thread.currentThread().getName() + " " + i);
if (i == 20) {
// 啓動兩個線程,但是實際上有三個線程,即main主線程
// 用戶啓動的多個線程的名字依次爲Thread-0、Thread-1、、、、
new ThreadDemo().start();
new ThreadDemo().start();
}
}


}
}


/*注意:該例中第一次出現的變量i是實例變量,而每次創建線程對象時候,Thread-0和Thread-1兩個線程對象不能共享實例變量i。
即使用繼承Thread方法創建線程對象時,多個線程之間無法共享線程類的實例變量。*/




2.實現Runnable接口
public interface Runnable
定義Runnable接口的實現類,並重寫該接口的run()方法,該run()方法同樣是該線程的執行體。創建該Runnable實現類的實例,並將此實例作爲Thread的target(即構造函數中的參數)來創建Thread對象(該Thread對象纔是真正的線程對象,只是該Thread對象負責執行其target的run()方法)。最後調用線程對象的start()方法來啓動該線程。

/**
 * @Description: TODO(用一句話描述該文件做什麼)
 * @author WEISANGENG
 * @date 2017年3月3日
 */
public class RunnableDemo implements Runnable {


private int i;


@Override
public void run() {
for (; i < 100; i++) {
// 當線程類實現Runnable接口時,只能通過Thread.currentThread()方法獲得當前線程
System.out.println(Thread.currentThread().getName() + " " + i);
}
}


public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
if (i == 20) {
ThreadDemo td = new ThreadDemo();
// 創建兩個Thread對象,並且均把Runnable接口實例對象作爲target
new Thread(td).start();
new Thread(td).start();
}
}


}


}




3.使用Callable和Future 
Executor是Java線程池的頂級接口
備註:ScheduledExecutorService描述的功能和Timer/TimerTask類似,解決那些需要任務重複執行的問題。這包括延遲時間一次性執行、延遲時間週期性執行以及固定延遲時間週期性執行等。當然了繼承ExecutorService的ScheduledExecutorService擁有ExecutorService的全部特性。
Executors是一個類

Executors類提供了若干個靜態方法,用於生成不同類型的線程池:

/** 
 * @Description: 啓動一個任務,然後等待任務的計算結果,如果等待時間超出預設定的超時時間,則中止任務。
 * @author WEISANGENG   
 * @date 2017年3月3日     
 */
public class ExecutorServiceTest {

public static void main(String[] args) {
System.out.println("Start ...");  
//創建一個可緩存的線程池。如果線程池的大小超過了處理任務所需要的線程,
//那麼就會回收部分空閒(60秒不執行任務)的線程,當任務數增加時,此線程池又可以智能的添加新線程來處理任務。
//此線程池不會對線程池大小做限制,線程池大小完全依賴於操作系統(或者說JVM)能夠創建的最大線程大小。
        ExecutorService exec = Executors.newCachedThreadPool();
          
        //testTask(exec, 15); // 任務成功結束後等待計算結果,不需要等到15秒  
        testTask(exec, 5); // 只等待5秒,任務還沒結束,所以將任務中止  
  
        exec.shutdown();  
        System.out.println("End!");
}
public static void testTask(ExecutorService exec, int timeout) {  
        MyTask task = new MyTask();
        //提交一個返回值的任務用於執行,返回一個表示任務的未決結果的 Future。
        //該 Future 的 get 方法在成功完成時將會返回該任務的結果。
        Future<Map<String, Object>> future = exec.submit(task);
        Map<String, Object> taskResult = null; 
        String failReason = null;  
        try {  
            // 等待計算結果,最長等待timeout秒,timeout秒後中止任務  
            taskResult = future.get(timeout, TimeUnit.SECONDS);  
        } catch (InterruptedException e) {  
            failReason = "主線程在等待計算結果時被中斷!";  
        } catch (ExecutionException e) {  
            failReason = "主線程等待計算結果,但計算拋出異常!";  
        } catch (TimeoutException e) {  
            failReason = "主線程等待計算結果超時,因此中斷任務線程!";  
        }  
        exec.shutdownNow(); 
        System.out.println("\ntaskResult : " + taskResult);  
        System.out.println("failReason : " + failReason);  
    }  



/**
 * 
 * @Description: 任務器
 * @author WEISANGENG
 * @date 2017年3月3日
 */
class MyTask implements Callable<Map<String, Object>> {  
 
    @Override  
    public Map<String, Object> call() throws Exception {  
        // 總計耗時約10秒  
        for (int i = 0; i < 10; i++) {  
            Thread.sleep(1000); // 睡眠1秒  
            System.out.println("第"+(i+1)+"秒");
        }
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("key", "weisg81");
        return map;  
    }  



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