更新時間:2020-02-11 09:57:51 來源:動力節點 瀏覽5666次
1、線程與進程的區別?
進程是操作系統分配資源的最小單元,線程是操作系統調度的最小單元。
一個程序至少有一個進程,一個進程至少有一個線程。
2、什么是多線程中的上下文切換?
多線程會共同使用一組計算機上的CPU,而線程數大于給程序分配的CPU數量時,為了讓各個線程都有執行的機會,就需要輪轉使用CPU。不同的線程切換使用CPU發生的切換數據等就是上下文切換。
3、死鎖與活鎖的區別,死鎖與饑餓的區別?
死鎖:是指兩個或兩個以上的進程(或線程)在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。
產生死鎖的必要條件:
互斥條件:所謂互斥就是進程在某一時間內獨占資源。
請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。
不剝奪條件:進程已獲得資源,在末使用完之前,不能強行剝奪。
循環等待條件:若干進程之間形成一種頭尾相接的循環等待資源關系。
活鎖:任務或者執行者沒有被阻塞,由于某些條件沒有滿足,導致一直重復嘗試,失敗,嘗試,失敗。
活鎖和死鎖的區別在于,處于活鎖的實體是在不斷的改變狀態,所謂的“活”,而處于死鎖的實體表現為等待;活鎖有可能自行解開,死鎖則不能。
饑餓:一個或者多個線程因為種種原因無法獲得所需要的資源,導致一直無法執行的狀態。
Java中導致饑餓的原因:
高優先級線程吞噬所有的低優先級線程的CPU時間。
線程被永久堵塞在一個等待進入同步塊的狀態,因為其他線程總是能在它之前持續地對該同步塊進行訪問。
線程在等待一個本身也處于永久等待完成的對象(比如調用這個對象的wait方法),因為其他線程總是被持續地獲得喚醒。
4、什么是Executors框架?
Executor框架是一個根據一組執行策略調用,調度,執行和控制的異步任務的框架。
無限制的創建線程會引起應用程序內存溢出。所以創建一個線程池是個更好的的解決方案,因為可以限制線程的數量并且可以回收再利用這些線程。利用Executors框架可以非常方便的創建一個線程池。
5、什么是阻塞隊列?阻塞隊列的實現原理是什么?如何使用阻塞隊列來實現生產者-消費者模型?
阻塞隊列(BlockingQueue)是一個支持兩個附加操作的隊列。
這兩個附加的操作是:在隊列為空時,獲取元素的線程會等待隊列變為非空。當隊列滿時,存儲元素的線程會等待隊列可用。
阻塞隊列常用于生產者和消費者的場景,生產者是往隊列里添加元素的線程,消費者是從隊列里拿元素的線程。阻塞隊列就是生產者存放元素的容器,而消費者也只從容器里拿元素。
JDK7提供了7個阻塞隊列。分別是:
ArrayBlockingQueue:一個由數組結構組成的有界阻塞隊列。
LinkedBlockingQueue:一個由鏈表結構組成的有界阻塞隊列。
PriorityBlockingQueue:一個支持優先級排序的無界阻塞隊列。
DelayQueue:一個使用優先級隊列實現的無界阻塞隊列。
SynchronousQueue:一個不存儲元素的阻塞隊列。
LinkedTransferQueue:一個由鏈表結構組成的無界阻塞隊列。
LinkedBlockingDeque:一個由鏈表結構組成的雙向阻塞隊列。
Java5之前實現同步存取時,可以使用普通的一個集合,然后在使用線程的協作和線程同步可以實現生產者,消費者模式,主要的技術就是用好,wait,notify,notifyAll,sychronized這些關鍵字。而在java5之后,可以使用阻塞隊列來實現,此方式大大簡少了代碼量,使得多線程編程更加容易,安全方面也有保障。
BlockingQueue接口是Queue的子接口,它的主要用途并不是作為容器,而是作為線程同步的的工具,因此他具有一個很明顯的特性,當生產者線程試圖向BlockingQueue放入元素時,如果隊列已滿,則線程被阻塞,當消費者線程試圖從中取出一個元素時,如果隊列為空,則該線程會被阻塞,正是因為它所具有這個特性,所以在程序中多個線程交替向BlockingQueue中放入元素,取出元素,它可以很好的控制線程之間的通信。
阻塞隊列使用最經典的場景就是socket客戶端數據的讀取和解析,讀取數據的線程不斷將數據放入隊列,然后解析線程不斷從隊列取數據解析。
6、什么是Callable和Future?
Callable接口類似于Runnable,從名字就可以看出來了,但是Runnable不會返回結果,并且無法拋出返回結果的異常,而Callable功能更強大一些,被線程執行后,可以返回值,這個返回值可以被Future拿到,也就是說,Future可以拿到異步執行任務的返回值。
可以認為是帶有回調的Runnable。
Future接口表示異步任務,是還沒有完成的任務給出的未來結果。所以說Callable用于產生結果,Future用于獲取結果。
7、什么是FutureTask?
使用ExecutorService啟動任務。
在Java并發程序中FutureTask表示一個可以取消的異步運算。它有啟動和取消運算、查詢運算是否完成和取回運算結果等方法。只有當運算完成的時候結果才能取回,如果運算尚未完成get方法將會阻塞。一個FutureTask對象可以對調用了Callable和Runnable的對象進行包裝,由于FutureTask也是調用了Runnable接口所以它可以提交給Executor來執行。
8、什么是競爭條件?你怎樣發現和解決競爭?
當多個進程都企圖對共享數據進行某種處理,而最后的結果又取決于進程運行的順序時,則我們認為這發生了競爭條件(racecondition)。
9、為什么我們調用start()方法時會執行run()方法,為什么我們不能直接調用run()方法?
當你調用start()方法時你將創建新的線程,并且執行在run()方法里的代碼。
但是如果你直接調用run()方法,它不會創建新的線程也不會執行調用線程的代碼,只會把run方法當作普通方法去執行。
10、Java中你怎樣喚醒一個阻塞的線程?
在Java發展史上曾經使用suspend()、resume()方法對于線程進行阻塞喚醒,但隨之出現很多問題,比較典型的還是死鎖問題。
解決方案可以使用以對象為目標的阻塞,即利用Object類的wait()和notify()方法實現線程阻塞。
首先,wait、notify方法是針對對象的,調用任意對象的wait()方法都將導致線程阻塞,阻塞的同時也將釋放該對象的鎖,相應地,調用任意對象的notify()方法則將隨機解除該對象阻塞的線程,但它需要重新獲取改對象的鎖,直到獲取成功才能往下執行;其次,wait、notify方法必須在synchronized塊或方法中被調用,并且要保證同步塊或方法的鎖對象與調用wait、notify方法的對象是同一個,如此一來在調用wait之前當前線程就已經成功獲取某對象的鎖,執行wait阻塞后當前線程就將之前獲取的對象鎖釋放。
以上就是動力節點Java培訓機構小編介紹的“2020年java編程筆試題及答案”的內容,希望對大家有幫助,如有疑問,請在線咨詢,有專業老師隨時為你服務。
相關推薦
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習