中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java線程核心機制是什么

發布時間:2021-11-03 17:21:40 來源:億速云 閱讀:130 作者:iii 欄目:編程語言

這篇文章主要介紹“Java線程核心機制是什么”,在日常操作中,相信很多人在Java線程核心機制是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Java線程核心機制是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

一、線程基本機制

1、概念描述

并發編程的特點是:可以將程序劃分為多個分離且獨立運行的任務,通過線程來驅動這些獨立的任務執行,從而提升整體的效率。下面提供一個基礎的演示案例。

2、應用案例

場景:假設有一個容器集合,需要拿出容器中的每個元素,進行加工處理,一般情況下直接遍歷就好,如果數據偏大,可以根據線程數量對集合切割,每個線程處理一部分數據,這樣處理時間就會減少很多。

public class ExtendThread01 {
    public static void main(String[] args) {
        List<Object> dataList = new ArrayList<>() ;
        dataList.add("A");
        dataList.add("B");
        dataList.add("C");
        // 把一個大的集合按照每個子集合的2個元素切割
        List<List<Object>> splitList = splitList(dataList,2);
        for (List<Object> list:splitList){
            System.out.println(list);
        }
        // 多線程處理
        for (List<Object> childList:splitList){
            ListTask listTask = new ListTask(childList) ;
            Thread runThread = new Thread(listTask);
            runThread.start();
        }
    }
    /**
     * List 集合切割
     */
    private static List<List<Object>> splitList (List<Object> list, int childSize) {
        if (list == null || list.size() == 0 || childSize < 1) {
            return null;
        }
        List<List<Object>> result = new ArrayList<>();
        int size = list.size();
        int count = (size + childSize - 1) / childSize ;
        for (int i = 0; i < count; i++) {
            List<Object> subList = list.subList(i * childSize, ((i + 1) * childSize > size ? size : childSize * (i + 1)));
            result.add(subList);
        }
        return result;
    }
}
class ListTask implements Runnable {
    private List<Object> list ;
    public ListTask (List<Object> list){this.list=list;}
    @Override
    public void run() {
        for (Object object:list){
            System.out.println(Thread.currentThread().getName()+"=="+object);
        }
    }
}

注意:這里案例只是對場景原理的實現,在開發中,是不允許這種操作的,需要使用線程池處理,后續會說。如果集合沒有控制好,導致大量創建Thread線程,導致內存溢出。

二、線程停止啟動

1、基礎流程

線程啟動后執行任務方法,在執行過程中可以被阻塞,休眠,喚醒,停止等一系列狀態操作。

線程休眠作用:當線程一部分任務執行完畢后進入休眠(阻塞)狀態,線程調度器可以切換到另外線程,這對分布任務的執行相對公平。

2、使用案例

public class ExtendThread02 {
    public static void main(String[] args) {
        StopThread stopThread = new StopThread() ;
        stopThread.start();
        // 標記當前線程停止信號,且拋出中斷異常,但沒有停止
        stopThread.interrupt();
        // 判斷當前線程是否已經是終止狀態
        System.out.println("1=="+stopThread.isInterrupted());
        // 清除當前線程的終止信號
        System.out.println("2=="+stopThread.interrupted());
        // 再次判斷當前線程狀態
        System.out.println("3=="+stopThread.isInterrupted());
        System.out.println("main end ...");
    }
}
class StopThread extends Thread {
    @Override
    public void run() {
        for (int i = 0 ; i < 10 ; i++){
            try {
                System.out.println(Thread.currentThread().getId()+"="+i);
                // 線程阻塞1秒
                Thread.sleep(1000);
            } catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    }
}

3、核心方法

sleep(long millis):線程休眠指定的時間,進入阻塞狀態;

interrupt():切換線程為中斷狀態,拋出中斷異常,不會停止線程,可以監視線程的中斷狀態并定義執行策略。

interrupted():清除調用該方法線程的中斷狀態,也不會影響線程的執行,且返回當前執行‘stopThread.interrupted()’的線程是否中斷,這里就是指main線程是否中斷。

isInterrupted():判斷調用該方法的線程是否已經是中斷狀態。

補刀一句:線程的這幾個方法極其容易混淆,需要斷點源碼追蹤一下看看,進入源碼方法,調用相關API查看一下狀態。(附斷點圖一張:)

Java線程核心機制是什么

三、線程優先級

1、基礎概念

CPU執行和處理線程的順序是不確定的,但是線程調度器傾向執行線程優先級高的線程,線程優先級高說明獲取CPU資源的概率高,或者獲取的執行時間分片多,但不代表優先級低的一定最后執行。

2、使用案例

public class ExtendThread03 {
    public static void main(String[] args) {
        Priority01 priority01 = new Priority01();
        priority01.start();
        System.out.println("priority01="+priority01.getPriority());
        Priority02 priority02 = new Priority02();
        priority02.start();
        System.out.println("priority02="+priority02.getPriority());
        priority01.setPriority(10);
        priority02.setPriority(1);
    }
}
class Priority01 extends Thread {
    @Override
    public void run() {
        for (int i = 0 ; i < 100 ; i++){
            System.out.println(Thread.currentThread().getName()+";i="+i);
        }
    }
}
class Priority02 extends Thread {
    @Override
    public void run() {
        for (int a = 0 ; a < 100 ; a++){
            System.out.println(Thread.currentThread().getName()+";a="+a);
        }
    }
}

注意:優先級范圍[MAX_PRIORITY=10,MIN_PRIORITY=1],如果超出范圍會拋出IllegalArgumentException異常。

建議:通常實際開發中,是不允許輕易修改線程運行的參數,容易引發認知之外的異常。

四、線程加入

1、基本概念

如果在線程A中,執行線程B的加入方法,那么A線程就會等待線程B執行完畢再返回繼續執行。

2、使用案例

public class ExtendThread04 {
    public static void main(String[] args) {
        JoinThreadA joinThreadA = new JoinThreadA() ;
        joinThreadA.start();
    }
}
class JoinThreadA extends Thread {
    @Override
    public void run() {
        System.out.println("缺水中...");
        JoinThreadB joinThreadB = new JoinThreadB() ;
        joinThreadB.start();
        try{
            joinThreadB.join();
        } catch (Exception e){
            e.printStackTrace();
        }
        System.out.println("喝水中...");
    }
}
class JoinThreadB extends Thread {
    @Override
    public void run() {
        System.out.println("買水中...");
        try{
            TimeUnit.SECONDS.sleep(2);
        } catch (Exception e){
            e.printStackTrace();
        }
        System.out.println("買到水...");
    }
}

注意:可以設置線程的加入時間join(long),畢竟等不到雪月風花,人生都是有時差,只能后會無期了。

五、本地線程

1、基本概念

本地的線程變量,底層維護ThreadLocalMap存儲值:

static class Entry extends WeakReference<ThreadLocal<?>> {
    Object value;
    Entry(ThreadLocal<?> k, Object v) {
        super(k);
        value = v;
    }
}

即以Key-Value鍵值對的方式存儲數據。如果對集合容器的源碼熟悉的話,這個Entry就是似曾相識感覺。

2、使用案例

public class ExtendThread05 {
    private static final ThreadLocal<Long> threadLocal = new ThreadLocal<>() ;
    private static void initBegin (){
        threadLocal.set(System.currentTimeMillis());
    }
    private static Long overTime (){
        return System.currentTimeMillis()-threadLocal.get();
    }
    public static void main(String[] args) throws Exception {
        ExtendThread05.initBegin();
        TimeUnit.SECONDS.sleep(3);
        System.out.println(ExtendThread05.overTime());
    }
}

ThreadLocal提供線程內存儲變量的能力,并且綁定到當前線程,通過get和set方法就可以得到和設置當前線程對應的值。這個在web開發中是常見的應用。

六、守護線程

1、基本概念

守護線程是支持輔助型線程,主要在程序中起到調度和支持性作用,當Jvm中非守護線程全部結束,守護線程也就會結束。

2、使用案例

public class ExtendThread06 {
    public static void main(String[] args) throws Exception {
        InputStreamReader is = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(is);
        String value = br.readLine();
        CheckThread checkThread = new CheckThread(value) ;
        checkThread.setDaemon(true);
        checkThread.start();
        System.out.println("Main End ...");
    }
}
class CheckThread extends Thread {
    private String spell ;
    public CheckThread (String spell){
        this.spell = spell ;
    }
    @Override
    public void run() {
        if (spell.startsWith("cs")){
            System.out.println(spell+":輸入正確");
        } else {
            System.out.println(spell+":輸入錯誤");
        }
        try {
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}

注意:守護線程需要顯式調用setDaemon(true);方法,這里可以看到main線程結束,整合程序就結束了,絲毫理會休眠中的守護線程。如果打斷非守護線程的休眠,試試會不會拋你一臉異常?

七、線程異常處理

1、機制描述

按照Java中異常處理機制,拋異常逐級降低,線程的任務方法run沒有拋異常,那重寫或者實現的方法自然不能直接throws異常出去。多線程中推薦捕獲異常,可以針對性處理機制。

2、使用案例

public class ExtendThread07 {
    public static void main(String[] args) {
        TryThread tryThread = new TryThread();
        tryThread.setName("try-name");
        // 定義運行中異常處理策略
        MyExe myExe = new MyExe() ;
        tryThread.setUncaughtExceptionHandler(myExe);
        tryThread.start();
    }
}
class TryThread extends Thread {
    @Override
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e){
            e.printStackTrace();
        }
        // 如何處理這里異常?
        Integer.parseInt("cicada") ;
    }
}
class MyExe implements Thread.UncaughtExceptionHandler {
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        System.out.println(t.getName()+";異常:"+e.getMessage());
    }
}

通過實現UncaughtExceptionHandler接口,并且線程要指定自定義異常處理對象,也可以處理未檢查的異常。

到此,關于“Java線程核心機制是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

安国市| 望谟县| 盐亭县| 和林格尔县| 涿鹿县| 衡山县| 明光市| 上虞市| 玛多县| 鹤壁市| 南宫市| 金阳县| 嘉鱼县| 阜康市| 孟津县| 日土县| 绥滨县| 麻江县| 永和县| 古丈县| 彭阳县| 克什克腾旗| 临泽县| 和顺县| 石台县| 射洪县| 老河口市| 武川县| 遂溪县| 英吉沙县| 靖宇县| 通州市| 阿拉善左旗| 阜新市| 沧源| 金昌市| 措勤县| 仪征市| 元氏县| 镇雄县| 博野县|