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