【Java并發(fā)學習】之線程的創(chuàng)建

【Java并發(fā)學習】之線程的創(chuàng)建

前言

Java并發(fā)一直是學習中的一個難點,之前雖然也有接觸一部分的內容,不過由于當時對于并發(fā)的認識不足,所以學習的效果不是很好,乘著最近有時間,重新拾起這一部分內容,重新學習一下,并且將學習過程的筆記整理出來,本小節(jié)主要學習的內容是線程的創(chuàng)建

線程的相關概念

談到并發(fā),不可避免的會涉及到進程、線程相關的概念問題,關于這部分,有比較詳細的定義,這里只是做個簡單的總結與梳理

進程

進程簡單的可以理解為是程序的一次執(zhí)行,是動態(tài)的一個概念,進程是現(xiàn)在計算機體系結構中資源分配的最小單位,這里需要注意的是,在沒有使用線程之前,進程還是系統(tǒng)進行調度的最小單位,不過由于對進程進行調度時所需要的時間以及空間代價比較大,所以現(xiàn)在進程一般只作為資源分配的最小單位,而不是調度的單位

線程

上面提到了,線程現(xiàn)在普通作為調度的最小單位,一個進程中至少包含一個線程,并且可以創(chuàng)建多個線程,這些線程之間共享進程所擁有的資源,并且可以執(zhí)行不同的任務

Java中多線程的創(chuàng)建

上面我們簡單了解了進程與線程的概念之后,接下來我們來學習Java中線程的創(chuàng)建與使用

在具體使用之前,我們需要明確兩個概念

任務,任務是指具線程所要執(zhí)行的具體內容,也就是所要執(zhí)行的代碼,需要明確的是,任務跟線程是沒有太明確的關系的,任務是描述,而線程則是具體執(zhí)行的工具

線程,線程只是負責執(zhí)行委托給它的任務,不清楚具體的內容是什么,因為具體的內容是定義在任務之中

明確了這兩個概念之后,接著來看下Java中所提供的實現(xiàn)多線程的工具

任務的描述

任務描述的方式總體上來看有兩種,一種是沒有具體返回值的任務,另一個一種是可以有返回值的任務,分別對應的接口是Runnable、Callable<T>

接下來我們來看下具體描述任務的方式


/**
 * 計算任務描述
 * 實現(xiàn)Runnable接口并且重寫run方法
 */
class CalcTask1 implements Runnable{

    /**
     * 具體的任務描述
     * 稍后具體的任務會有對應的線程來執(zhí)行
     */
    @Override
    public void run() {
        int sum = 0;
        for (int i = 0; i < 100000; i++){
            sum +=i ;
        }
        System.out.println(sum);
    }
}


/**
 * 計算任務描述
 * 實現(xiàn)Callable接口并重寫call方法
 */
class CalcTask2 implements Callable<Integer>{

    /**
     * 具體的任務描述
     * 稍后具體的任務會有對應的線程來執(zhí)行
     */
    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 0; i < 100000; i++){
            sum +=i ;
        }
        return sum;
    }
}

需要注意的是,Callable接口是泛型設計,需要為其指定對應的返回類型

除了上面的這兩種描述方式外,其實還有另外一種,那就是直接繼承Thread類,并且重寫對應的run方法,這種方式也是可以用于描述對應的任務,不過會導致具體任務與對應的線程綁定在一起


/**
 * 通過繼承Thread并且重寫run方式來描述任務
 */
class CalcTask3 extends Thread{

    @Override
    public void run() {
        int sum = 0;
        for (int i = 0; i < 100000; i++){
            sum +=i ;
        }
        System.out.println(sum);
    }
}

使用多線程的方式

上面我們提到了,在Java中,在使用多線程的時候,一般是把操作邏輯與具體的執(zhí)行者分開,這種實現(xiàn)方式看上去比較麻煩,但是實際上將實現(xiàn)邏輯與具體執(zhí)行者分離是一種非常好的設計,由于線程的創(chuàng)建以及回收時非常耗費資源的,所以為了避免頻繁的創(chuàng)建與回收線程,我們可以采用線程池的方式來管理線程,而如果是將實現(xiàn)邏輯與具體的執(zhí)行者綁定,就無法充分利用這種優(yōu)勢了

從本質上來講,實現(xiàn)多線程的方式只有一種,那就是創(chuàng)建對應的線程,并且將具體的操作邏輯交給線程,并且調用對應線程的start方法,如下所示


// 創(chuàng)建對應的任務
Runnable calcTask = new CalcTask1();
// 將任務提交給線程
// 這里需要注意的是,如果是直接繼承自Thread,則直接調用對應的
// 線程對象的run方法即可
Thread executor = new Thread(calcTask);
// 啟動線程
executor.start();

上面這種實現(xiàn)方式是比較原始的方式,通過這種方式來啟動多線程的缺點是,在需要使用線程的時候,必須自己手動創(chuàng)建,也就是說,無法充分利用線程池的優(yōu)勢,而且,還必須自己管理線程的生命周期,于是,在JDK5的時候,Java引入了一個通用的線程執(zhí)行框架Executor(關于Executor將在后面學習到),從而簡化了這一系列的操作過程


// 獲取一個ExecutorService實例
ExecutorService service = Executors.newCachedThreadPool();
// 創(chuàng)建對應的任務
Runnable calcTask = new CalcTask1();
// 將任務提交給ExecutorService
service.submit(calcTask);
// 關閉對應的ExecutorService
service.shutdown();

總結

本小節(jié)主要學習了進程、線程的相關概念,以及在Java中描述任務的方式,實現(xiàn) Runnable、Callable<T>以及繼承Thread,并且學習學習了啟動線程來驅動對應任務的方式,直接將任務交給Thread對象,或者將其交給Executor框架

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 從三月份找實習到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發(fā)崗...
    時芥藍閱讀 42,798評論 11 349
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,030評論 25 709
  • 公交車外雨滴落在窗邊順著窗戶一滴滴的流了下來,天也是灰蒙蒙的,粉條靠著窗戶,心情很應景的也響應著悲傷,眼角好像有什...
    大兔閱讀 313評論 0 0
  • 表姐和外婆吵架了。 看到姐姐發(fā)的一條朋友圈不對勁,就問怎么了。姐姐說和外婆吵架了。外婆是我心里的一處柔軟,姐姐和我...
    月下0204閱讀 1,193評論 0 1
  • 499. The Maze III 想法很簡單,有點懶得寫。在heap里存上 dist,path,cur_pos,...
    健時總向亂中忙閱讀 189評論 0 0

友情鏈接更多精彩內容