面試題之併發相關專欄四

一、Java中的線程池是如何實現的?

  • 在Java中,所謂的線程池中的線程,其實是被抽象爲了一個靜態內部類Worker,基於AQS實現,存放在線程池的HashSet workers成員變量中;
  • 需要執行的任務存放在成員變量workQueue中,workQueue是一個阻塞隊列;
  • 線程池的基本思想就是:從workQueue隊列中不斷取出需要執行的任務,放在Workers中進行執行;

二、如何自定義線程池?

自定義線程池是通過new ThreadPoolExecutor()指定對應的參數創建,下面給出一個示例:

private static ExecutorService getExecutorService() {
        return new ThreadPoolExecutor(
                5,  //常駐核心線程的數量
                5, //線程池中能夠容納同時執行的最大線程數
                0L, //多餘的空閒線程的存活時間
                TimeUnit.MILLISECONDS, //時間單位:毫秒
                new LinkedBlockingQueue<>(5), //阻塞隊列
                Executors.defaultThreadFactory(), //默認線程池生產工廠
                new ThreadPoolExecutor.AbortPolicy() //拒絕策略
        );
    }

三、線程池中的線程是怎麼創建的?它是一開始就隨着線程池的啓動創建好的麼? 

線程池默認初始化後不啓動worker,等待有請求時才啓動。

線程池執行流程:

  

文字描述:任務進來時,首先執行判斷,判斷常駐核心線程是否處於空閒狀態,如果不是,核心線程就先就執行任務,如果核心線程已滿,則判斷任務隊列是否有地方存放該任務,如果有,就將任務保存在任務隊列中,等待執行,如果滿了,在判斷最大可容納的線程數,如果沒有超出這個數量,就創建非核心線程執行任務,如果超出了,就調用handler實現拒絕策略。 

四、如何在Java線程池中提交線程任務?

  • execute():  ExecutorService.execute()方法接收一個runnable示例,用來執行一個任務;
  • submit():  ExecutorService.submit() 方法返回的是Future對象,可以使用get()獲取線程執行結果;

五、什麼是Java的內存模型,Java中各個線程是怎麼彼此看到對方變量的?

Java的內存模型定義了程序中各個變量的訪問規則,即在虛擬機中將變量存儲到內存和從內存中取出這樣的底層細節。此處的變量包括實例字段、靜態字段和構成數組對象的元素,但是不包括局部變量和方法參數,因爲這些是線程私有,不會被共享,不存在資源競爭問題。

Java中定義了主內存和工作內存的概念:所有的變量都存儲在主內存中,每條線程還有自己的工作內存,保存了被該線程使用到的變量的主內存的副本拷貝,線程對變量的所有操作(讀取、賦值)都必須在自己的工作內存中完成,不能直接讀寫主內存中的變量,不同的線程之間也無法直接訪問對方工作內存的變量,線程之間變量值的傳遞需要通過主內存來完成。

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