線程併發學習----Thread、Runnable、Callable

線程併發學習

線程併發學習—-核心概念(轉載)
線程併發學習—-線程阻塞(sleep、wait、notifyAll、notify、join)
線程併發學習—-線程阻塞(synchronized)
線程併發學習—-線程阻塞(lock)
線程併發學習—-Thread、Runnable、Callable
線程併發學習—-隊列(Queue)
spring學習—-線程池
java中一些鎖概念整理(轉載)

線程簡介

線程狀態轉換圖(網上load)

這裏寫圖片描述

線程狀態介紹

  • 新建狀態(New):新創建了一個線程對象。
  • 就緒狀態(Runnable):線程對象創建後,其他線程調用了該對象的start()方法。該狀態的線程位於可運行線程池中,變得可運行,等待獲取CPU的使用權。
  • 運行狀態(Running):就緒狀態的線程獲取了CPU,執行程序代碼。
  • 阻塞狀態(Blocked):阻塞狀態是線程因爲某種原因放棄CPU使用權,暫時停止運行。直到線程進入就緒狀態,纔有機會轉到運行狀態。

    阻塞的情況分三種:
    (一)、等待阻塞:運行的線程執行wait()方法,JVM會把該線程放入等待池中。
    (二)、同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程佔用,則JVM會把該線程放入鎖池中。
    (三)、其他阻塞:運行的線程執行sleep()或join()方法,或者發出了I/O請求時,JVM會把該線程置爲阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態。

  • 死亡狀態(Dead):線程執行完了或者因異常退出了run()方法,該線程結束生命週期。

java中多線程實現

繼承Thread

例子

//繼承Thread類
public class ThreadDemo extends Thread{
    //實現Thread類run方法
    @Override
    public void run(){
        System.out.println("這是線程的run方法");
    }

    public static void main(String[] args) {
        ThreadDemo threadDemo = new ThreadDemo();
        //啓動線程,爲什麼是start 不是run見源碼
        threadDemo.start();
    }
}

實現Runnable

例子

public class RunnableDemo implements Runnable {
    @Override
    public void run() {
        System.out.println("這是實現Runnable的run方法1");
    }

    public static void main(String[] args) {
        //實現Runnable接口實現
        new Thread(new RunnableDemo()).start();
        //匿名內部類實現
        new Thread(new Runnable(){
            @Override
            public void run() {
                System.out.println("這是實現Runnable的run方法2");
            }
        }).start();
    }
}

實現Callable

例子

public class CallableDemo implements Callable<String>{
    @Override
        public String call() throws Exception {
        System.out.println("這是Callable的call方法");
        return "success";
    }

    public static void main(String[] args) throws Exception{
        CallableDemo callableDemo = new CallableDemo();
        ExecutorService exec = Executors.newCachedThreadPool();
        ArrayList<Future<String>> results = new ArrayList();    //Future 相當於是用來存放Executor執行的結果的一種容器
        for (int i = 0; i < 10; i++) {
            results.add(exec.submit(new CallableDemo()));
        }
        for (Future<String> fs : results) {
            if (fs.isDone()) {
                System.out.println(fs.get());
            } else {
                System.out.println("Future result is not yet complete");
            }
        }
        exec.shutdown();
    }
}

三種方式分析

繼承Thread實現簡單,但有侷限性java的類只能繼承一個父類(一般不會使用)
實現接口更靈活,避免繼承的侷限,可以實現多個接口

實現Runnable與Callable大體一樣,區別

  • Runnable使用run()方法,Callable使用call()方法
  • run方法沒有返回值,call方法有返回值
  • run不能拋出受檢查異常 ,call可以拋出受檢查異常。如:ClassNotFoundException

Runnable通過Thread包裝實現 或者 FutureTask包裝實現
Callable一般通過ExecutorService包裝,本質是通過FutureTask實現

java線程類圖分析

這裏寫圖片描述

ThreadPoolExecutor的execute方法參數只能爲Runnable
AbstractExecutorService的submit方法可以將Runnable和Callable包裝爲FutureTask,再調用execute方法

FutureTask實現RunnableFuture實現Runnable接口

ThreadPoolExecutor的execute方法,addWorker—》Worker—》默認使用DefaultThreadFactory—》new Thread—》執行start方法啓動線程,執行FutureTask的run方法

詳情見http://blog.csdn.net/eos2009/article/details/78617618的源碼 AbstractExecutorService

自己的理解:java線程的本質 Thread 的start創建線程,執行run方法實現

源碼

Thread

//Thread 實現Runnable接口
public class Thread implements Runnable {

public synchronized void start() {
        if (threadStatus != 0)
            throw new IllegalThreadStateException();
        group.add(this);

        boolean started = false;
        try {
            //通過調用底層start0方法創建執行線程
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }
    //操作系統底層函數
    private native void start0();

FutureTask

    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }

    //將runnable任務包裝爲callable 使其有返回值  使用Executors工具類
    public FutureTask(Runnable runnable, V result) {
        this.callable = Executors.callable(runnable, result);
        this.state = NEW;       // ensure visibility of callable
    }

Executors

//
public static <T> Callable<T> callable(Runnable task, T result) {
        if (task == null)
            throw new NullPointerException();
        return new RunnableAdapter<T>(task, result);
    }

static final class RunnableAdapter<T> implements Callable<T> {
        final Runnable task;
        final T result;
        RunnableAdapter(Runnable task, T result) {
            this.task = task;
            this.result = result;
        }
        public T call() {
            //底層實現使用Runnable接口run方法
            task.run();
            return result;
        }
    }

參考資料

http://blog.csdn.net/pcceo1/article/details/52444730

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