目錄
52、什么是線程池? 為什么要使用它?
53、怎么檢測一個線程是否擁有鎖?
54、你如何在 Java 中獲取線程堆棧?
55、JVM 中哪個參數(shù)是用來控制線程的棧堆棧小的?
56、Thread 類中的 yield 方法有什么作用?
57、Java 中 ConcurrentHashMap 的并發(fā)度是什么?
58、Java 中 Semaphore 是什么?
59、Java 線程池中 submit() 和 execute()方法有什么區(qū)別?
60、什么是阻塞式方法?
61、Java 中的 ReadWriteLock 是什么?
62、volatile 變量和 atomic 變量有什么不同?
63、可以直接調用 Thread 類的 run ()方法么?
64、如何讓正在運行的線程暫停一段時間?
65、你對線程優(yōu)先級的理解是什么?
66、什么是線程調度器(Thread Scheduler)和時間分片(Time Slicing )?
67、你如何確保 main()方法所在的線程是 Java 程序最后結束的線程?
68、線程之間是如何通信的?
69、為什么線程通信的方法 wait(), notify()和 notifyAll()被定義在 Object 類里?
70、為什么 wait(), notify()和 notifyAll ()必須在同步方法或者同步塊中被調用?
71、為什么 Thread 類的 sleep()和 yield ()方法是靜態(tài)的?
72、如何確保線程安全?
73、同步方法和同步塊,哪個是更好的選擇?
74、如何創(chuàng)建守護線程?
75、什么是 Java Timer 類?如何創(chuàng)建一個有特定時間間隔的任務?
52、什么是線程池? 為什么要使用它?
創(chuàng)建線程要花費昂貴的資源和時間,如果任務來了才創(chuàng)建線程那么響應時間會變長,而且一個進程能創(chuàng)建的線程數(shù)有限。為了避免這些問題,在程序啟動的時候就創(chuàng)建若干線程來響應處理,它們被稱為線程池,里面的線程叫工作線程。從JDK1.5 開始,Java API 提供了 Executor 框架讓你可以創(chuàng)建不同的線程池。
53、怎么檢測一個線程是否擁有鎖?
在 java.lang.Thread 中有一個方法叫 holdsLock(),它返回 true 如果當且僅當當前線程擁有某個具體對象的鎖。
54、你如何在 Java 中獲取線程堆棧?
kill -3 [java pid]
不會在當前終端輸出,它會輸出到代碼執(zhí)行的或指定的地方去。比如,kill -3 tomcat pid, 輸出堆棧到 log 目錄下。
Jstack [java pid]
這個比較簡單,在當前終端顯示,也可以重定向到指定文件中。
-JvisualVM:Thread Dump
不做說明,打開 JvisualVM 后,都是界面操作,過程還是很簡單的。
55、JVM 中哪個參數(shù)是用來控制線程的棧堆棧小的?
-Xss 每個線程的棧大小
56、Thread 類中的 yield 方法有什么作用?
使當前線程從執(zhí)行狀態(tài)(運行狀態(tài))變?yōu)榭蓤?zhí)行態(tài)(就緒狀態(tài))。
當前線程到了就緒狀態(tài),那么接下來哪個線程會從就緒狀態(tài)變成執(zhí)行狀態(tài)呢?可能是當前線程,也可能是其他線程,看系統(tǒng)的分配了。
57、Java 中 ConcurrentHashMap 的并發(fā)度是什么?
ConcurrentHashMap 把實際 map 劃分成若干部分來實現(xiàn)它的可擴展性和線程安全。這種劃分是使用并發(fā)度獲得的,它是 ConcurrentHashMap 類構造函數(shù)的一個可選參數(shù),默認值為 16,這樣在多線程情況下就能避免爭用。
在 JDK8 后,它摒棄了 Segment(鎖段)的概念,而是啟用了一種全新的方式實現(xiàn),利用 CAS 算法。同時加入了更多的輔助變量來提高并發(fā)度,具體內容還是查看源碼吧。
58、Java 中 Semaphore 是什么?
Java 中的 Semaphore 是一種新的同步類,它是一個計數(shù)信號。從概念上講,從概念上講,信號量維護了一個許可集合。如有必要,在許可可用前會阻塞每一個acquire(),然后再獲取該許可。每個 release()添加一個許可,從而可能釋放一個正在阻塞的獲取者。但是,不使用實際的許可對象,Semaphore 只對可用許可的號碼進行計數(shù),并采取相應的行動。信號量常常用于多線程的代碼中,比如數(shù)據(jù)庫連接池。
59、Java 線程池中 submit() 和 execute()方法有什么區(qū)別?
兩個方法都可以向線程池提交任務,execute()方法的返回類型是 void,它定義在Executor 接口中。
而 submit()方法可以返回持有計算結果的 Future 對象,它定義在ExecutorService 接口中,它擴展了 Executor 接口,其它線程池類像ThreadPoolExecutor 和 ScheduledThreadPoolExecutor 都有這些方法。
60、什么是阻塞式方法?
阻塞式方法是指程序會一直等待該方法完成期間不做其他事情,ServerSocket 的accept()方法就是一直等待客戶端連接。這里的阻塞是指調用結果返回之前,當前線程會被掛起,直到得到結果之后才會返回。此外,還有異步和非阻塞式方法在任務完成前就返回。
61、Java 中的 ReadWriteLock 是什么?
讀寫鎖是用來提升并發(fā)程序性能的鎖分離技術的成果。
62、volatile 變量和 atomic 變量有什么不同?
Volatile 變量可以確保先行關系,即寫操作會發(fā)生在后續(xù)的讀操作之前, 但它并不能保證原子性。例如用 volatile 修飾 count 變量那么 count++ 操作就不是原子性的。
而 AtomicInteger 類提供的 atomic 方法可以讓這種操作具有原子性如getAndIncrement()方法會原子性的進行增量操作把當前值加一,其它數(shù)據(jù)類型和引用變量也可以進行相似操作。
63、可以直接調用 Thread 類的 run ()方法么?
當然可以。但是如果我們調用了 Thread 的 run()方法,它的行為就會和普通的方法一樣,會在當前線程中執(zhí)行。為了在新的線程中執(zhí)行我們的代碼,必須使用Thread.start()方法。
64、如何讓正在運行的線程暫停一段時間?
我們可以使用 Thread 類的 Sleep()方法讓線程暫停一段時間。需要注意的是,這并不會讓線程終止,一旦從休眠中喚醒線程,線程的狀態(tài)將會被改變?yōu)?Runnable,并且根據(jù)線程調度,它將得到執(zhí)行。
65、你對線程優(yōu)先級的理解是什么?
每一個線程都是有優(yōu)先級的,一般來說,高優(yōu)先級的線程在運行時會具有優(yōu)先權,但這依賴于線程調度的實現(xiàn),這個實現(xiàn)是和操作系統(tǒng)相關的(OS dependent)。我們可以定義線程的優(yōu)先級,但是這并不能保證高優(yōu)先級的線程會在低優(yōu)先級的線程前執(zhí)行。線程優(yōu)先級是一個 int 變量(從 1-10),1 代表最低優(yōu)先級,10 代表最高優(yōu)先級。
java 的線程優(yōu)先級調度會委托給操作系統(tǒng)去處理,所以與具體的操作系統(tǒng)優(yōu)先級有關,如非特別需要,一般無需設置線程優(yōu)先級。
66、什么是線程調度器(Thread Scheduler)和時間分片(Time Slicing )?
線程調度器是一個操作系統(tǒng)服務,它負責為 Runnable 狀態(tài)的線程分配 CPU 時間。一旦我們創(chuàng)建一個線程并啟動它,它的執(zhí)行便依賴于線程調度器的實現(xiàn)。同上一個問題,線程調度并不受到 Java 虛擬機控制,所以由應用程序來控制它是更好的選擇(也就是說不要讓你的程序依賴于線程的優(yōu)先級)。
時間分片是指將可用的 CPU 時間分配給可用的 Runnable 線程的過程。分配 CPU時間可以基于線程優(yōu)先級或者線程等待的時間。
67、你如何確保 main()方法所在的線程是 Java 程序最后結束的線程?
我們可以使用 Thread 類的 join()方法來確保所有程序創(chuàng)建的線程在 main()方法退出前結束。
68、線程之間是如何通信的?
當線程間是可以共享資源時,線程間通信是協(xié)調它們的重要的手段。Object 類中wait()\notify()\notifyAll()方法可以用于線程間通信關于資源的鎖的狀態(tài)。
69、為什么線程通信的方法 wait(), notify()和 notifyAll()被定義在 Object 類里?
Java 的每個對象中都有一個鎖(monitor,也可以成為監(jiān)視器) 并且 wait(),notify()等方法用于等待對象的鎖或者通知其他線程對象的監(jiān)視器可用。在 Java 的線程中并沒有可供任何對象使用的鎖和同步器。這就是為什么這些方法是 Object 類的一部分,這樣 Java 的每一個類都有用于線程間通信的基本方法。
70、為什么 wait(), notify()和 notifyAll ()必須在同步方法或者同步塊中被調用?
當一個線程需要調用對象的 wait()方法的時候,這個線程必須擁有該對象的鎖,接著它就會釋放這個對象鎖并進入等待狀態(tài)直到其他線程調用這個對象上的 notify()方法。同樣的,當一個線程需要調用對象的 notify()方法時,它會釋放這個對象的鎖,以便其他在等待的線程就可以得到這個對象鎖。由于所有的這些方法都需要線程持有對象的鎖,這樣就只能通過同步來實現(xiàn),所以他們只能在同步方法或者同步塊中被調用。
71、為什么 Thread 類的 sleep()和 yield ()方法是靜態(tài)的?
Thread 類的 sleep()和 yield()方法將在當前正在執(zhí)行的線程上運行。所以在其他處于等待狀態(tài)的線程上調用這些方法是沒有意義的。這就是為什么這些方法是靜態(tài)的。它們可以在當前正在執(zhí)行的線程中工作,并避免程序員錯誤的認為可以在其他非運行線程調用這些方法。
72、如何確保線程安全?
在 Java 中可以有很多方法來保證線程安全——同步,使用原子類(atomic concurrent classes),實現(xiàn)并發(fā)鎖,使用 volatile 關鍵字,使用不變類和線程安全類。
73、同步方法和同步塊,哪個是更好的選擇?
同步塊是更好的選擇,因為它不會鎖住整個對象(當然你也可以讓它鎖住整個對象)。同步方法會鎖住整個對象,哪怕這個類中有多個不相關聯(lián)的同步塊,這通常會導致他們停止執(zhí)行并需要等待獲得這個對象上的鎖。同步塊更要符合開放調用的原則,只在需要鎖住的代碼塊鎖住相應的對象,這樣從側面來說也可以避免死鎖。
74、如何創(chuàng)建守護線程?
使用 Thread 類的 setDaemon(true)方法可以將線程設置為守護線程,需要注意的是,需要在調用 start()方法前調用這個方法,否則會拋出IllegalThreadStateException 異常。
75、什么是 Java Timer 類?如何創(chuàng)建一個有特定時間間隔的任務?
java.util.Timer 是一個工具類,可以用于安排一個線程在未來的某個特定時間執(zhí)行。Timer 類可以用安排一次性任務或者周期任務。
java.util.TimerTask 是一個實現(xiàn)了 Runnable 接口的抽象類,我們需要去繼承這個類來創(chuàng)建我們自己的定時任務并使用 Timer 去安排它的執(zhí)行。
要想了解更多:
千題千解·Java面試寶典_時光の塵的博客-CSDN博客文章來源:http://www.zghlxwxcb.cn/news/detail-725798.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-725798.html
到了這里,關于互聯(lián)網(wǎng)Java工程師面試題·Java 并發(fā)編程篇·第五彈的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!