為什么需要線程+面試題_第1頁
為什么需要線程+面試題_第2頁
為什么需要線程+面試題_第3頁
為什么需要線程+面試題_第4頁
為什么需要線程+面試題_第5頁
已閱讀5頁,還剩11頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

文檔來源網絡侵權聯系刪除PAGEPAGE1僅供參考為什么需要線程+面試題線程介紹線程(Thread)是程序運行的執(zhí)行單元,依托于進程存在。一個進程中可以包含多個線程,多線程可以共享一塊內存空間和一組系統資源,因此線程之間的切換更加節(jié)省資源、更加輕量化,因而也被稱為輕量級的進程。什么是進程進程(Processes)是程序的一次動態(tài)執(zhí)行,是系統進行資源分配和調度的基本單位,是操作系統運行的基礎,通常每一個進程都擁有自己獨立的內存空間和系統資源。簡單來說,進程可以被當做是一個正在運行的程序。為什么需要線程程序的運行必須依靠進程,進程的實際執(zhí)行單元就是線程。為什么需要多線程多線程可以提高程序的執(zhí)行性能。例如,有個90平方的房子,一個人打掃需要花費30分鐘,三個人打掃就只需要10分鐘,這三個人就是程序中的“多線程”。線程使用線程的創(chuàng)建,分為以下三種方式:繼承Thread類,重寫run方法實現Runnable接口,實現run方法實現Callable接口,實現call方法下面分別來看看線程創(chuàng)建和使用的具體代碼。1)繼承Thread類請參考以下代碼:classThreadTest{

publicstaticvoidmain(String[]args)throwsException{

MyThreadthread=newMyThread();

thread.start();

}

}

classMyThreadextendsThread{

@Override

publicvoidrun(){

System.out.println("Thread");

}

}以上程序執(zhí)行結果如下:Thread2)實現Runnable接口請參考以下代碼:classThreadTest{

publicstaticvoidmain(String[]args){

MyRunnablerunnable=newMyRunnable();

newThread(runnable).start();

}

}

classMyRunnableimplementsRunnable{

@Override

publicvoidrun(){

System.out.println("Runnable");

}

}以上程序執(zhí)行結果如下:Runnable3)實現Callable接口請參考以下代碼:classThreadTest{

publicstaticvoidmain(String[]args)throwsException{

MyCallablecallable=newMyCallable();

//定義返回結果

FutureTask<String>result=newFutureTask(callable);

//執(zhí)行程序

newThread(result).start();

//輸出返回結果

System.out.println(result.get());

}

}

classMyCallableimplementsCallable{

@Override

publicStringcall(){

System.out.println("Callable");

return"Success";

}

}以上程序執(zhí)行結果如下:CallableSuccess可以看出,Callable的調用是可以有返回值的,它彌補了之前調用線程沒有返回值的情況,它是隨著JDK1.5一起發(fā)布的。4)JDK8創(chuàng)建線程JDK8之后可以使用Lambda表達式很方便地創(chuàng)建線程,請參考以下代碼:newThread(()->System.out.println("LambdaOfThread.")).start();線程高級用法線程等待使用wait()方法實現線程等待,代碼如下:System.out.println(LocalDateTime.now());

Objectlock=newObject();

Threadthread=newThread(()->{

synchronized(lock){

try{

//1秒鐘之后自動喚醒

lock.wait(1000);

System.out.println(LocalDateTime.now());

}catch(InterruptedExceptione){

e.printStackTrace();

}

}

});

thread.start();以上程序執(zhí)行結果如下:2019-06-22T20:53:08.7762019-06-22T20:53:09.788注意:當使用wait()方法時,必須先持有當前對象的鎖,否則會拋出異常java.lang.IllegalMonitorStateException。線程喚醒使用notify()/notifyAll()方法喚醒線程。notify()方法隨機喚醒對象的等待池中的一個線程;notifyAll()喚醒對象的等待池中的所有線程。使用如下:Objectlock=newObject();

lock.wait();

lock.notify();

//lock.notifyAll();線程休眠//休眠1秒

Thread.sleep(1000);等待線程執(zhí)行完成ThreadjoinThread=newThread(()->{

try{

System.out.println("執(zhí)行前");

Thread.sleep(1000);

System.out.println("執(zhí)行后");

}catch(InterruptedExceptione){

e.printStackTrace();

}

});

joinThread.start();

joinThread.join();

System.out.println("主程序");以上程序執(zhí)行結果:執(zhí)行前執(zhí)行后主程序yield交出CPU執(zhí)行權newThread(){

@Override

publicvoidrun(){

for(inti=1;i<10;i++){

if(i==5){

//讓同優(yōu)先級的線程有執(zhí)行的機會

this.yield();

}

}

}

}.start();注意:yield方法是讓同優(yōu)先級的線程有執(zhí)行的機會,但不能保證自己會從正在運行的狀態(tài)迅速轉換到可運行的狀態(tài)。線程中斷使用System.exit(0)可以讓整個程序退出;要中斷單個線程,可配合interrupt()對線程進行“中斷”。

使用代碼如下:ThreadinterruptThread=newThread(){

@Override

publicvoidrun(){

for(inti=0;i<Integer.MAX_VALUE;i++){

System.out.println("i:"+i);

if(this.isInterrupted()){

break;

}

}

}

};

interruptThread.start();

Thread.sleep(10);

interruptTerrupt();線程優(yōu)先級在Java語言中,每一個線程有一個優(yōu)先級,默認情況下,一個線程繼承它父類的優(yōu)先級。可以使用setPriority方法設置(1-10)優(yōu)先級,默認的優(yōu)先級是5,數字越大表示優(yōu)先級越高,優(yōu)先級越高的線程可能優(yōu)先被執(zhí)行的概率就越大。

設置優(yōu)先級的代碼如下:Threadthread=newThread(()->System.out.println("Java"));

thread.setPriority(10);

thread.start();死鎖死鎖是指兩個或兩個以上的進程在執(zhí)行過程中,由于競爭資源或者由于彼此通信而造成的一種阻塞的現象,若無外力作用,它們都將無法推進下去。

比如,當線程A持有獨占鎖a,并嘗試去獲取獨占鎖b的同時,線程B持有獨占鎖b,并嘗試獲取獨占鎖a的情況下,就會發(fā)生AB兩個線程由于互相持有對方需要的鎖,而發(fā)生的阻塞現象,我們稱為死鎖。

死鎖示意圖如下所示:

死鎖代碼:Objectobj1=newObject();

Objectobj2=newObject();

//線程1擁有對象1,想要等待獲取對象2

newThread(){

@Override

publicvoidrun(){

synchronized(obj1){

try{

Thread.sleep(1000);

}catch(InterruptedExceptione){

e.printStackTrace();

}

synchronized(obj2){

System.out.println(Thread.currentThread().getName());

}

}

}

}.start();

//線程2擁有對象2,想要等待獲取對象1

newThread(){

@Override

publicvoidrun(){

synchronized(obj2){

try{

Thread.sleep(1000);

}catch(InterruptedExceptione){

e.printStackTrace();

}

synchronized(obj1){

System.out.println(Thread.currentThread().getName());

}

}

}

}.start();相關面試題1.線程和進程有什么區(qū)別和聯系?答:從本質上來說,線程是進程的實際執(zhí)行單元,一個程序至少有一個進程,一個進程至少有一個線程,它們的區(qū)別主要體現在以下幾個方面:進程間是獨立的,不能共享內存空間和上下文,而線程可以;進程是程序的一次執(zhí)行,線程是進程中執(zhí)行的一段程序片段;線程占用的資源比進程少。2.如何保證一個線程執(zhí)行完再執(zhí)行第二個線程?答:使用join()方法,等待上一個線程的執(zhí)行完之后,再執(zhí)行當前線程。

示例代碼:ThreadjoinThread=newThread(()->{

try{

System.out.println("執(zhí)行前");

Thread.sleep(1000);

System.out.println("執(zhí)行后");

}catch(InterruptedExceptione){

e.printStackTrace();

}

});

joinThread.start();

joinThread.join();

System.out.println("主程序");3.線程有哪些常用的方法?答:線程的常用方法如下:currentThread():返回當前正在執(zhí)行的線程引用getName():返回此線程的名稱setPriority()/getPriority():設置和返回此線程的優(yōu)先級isAlive():檢測此線程是否處于活動狀態(tài),活動狀態(tài)指的是程序處于正在運行或準備運行的狀態(tài)sleep():使線程休眠join():等待線程執(zhí)行完成yield():讓同優(yōu)先級的線程有執(zhí)行的機會,但不能保證自己會從正在運行的狀態(tài)迅速轉換到可運行的狀態(tài)interrupted():是線程處于中斷的狀態(tài),但不能真正中斷線程4.wait()和sleep()有什么區(qū)別?答:wait()和sleep()的區(qū)別主要體現在以下三個方面。存在類的不同:sleep()來自Thread,wait()來自Object。釋放鎖:sleep()不釋放鎖;wait()釋放鎖。用法不同:sleep()時間到會自動恢復;wait()可以使用notify()/notifyAll()直接喚醒。5.守護線程是什么?答:守護線程是一種比較低級別的線程,一般用于為其他類別線程提供服務,因此當其他線程都退出時,它也就沒有存在的必要了。例如,JVM(Java虛擬機)中的垃圾回收線程。6.線程有哪些狀態(tài)?答:在JDK8中,線程的狀態(tài)有以下六種。NEW:尚未啟動RUNNABLE:正在執(zhí)行中BLOCKED:阻塞(被同步鎖或者IO鎖阻塞)WAITING:永久等待狀態(tài)TIMED_WAITING:等待指定的時間重新被喚醒的狀態(tài)TERMINATED:執(zhí)行完成題目分析:JDK8線程狀態(tài)的源碼如下圖所示:

7.線程中的start()和run()有那些區(qū)別?答:start()方法用于啟動線程,run()方法用于執(zhí)行線程的運行時代碼。run()可以重復調用,而start()只能調用一次。8.產生死鎖需要具備哪些條件?答:產生死鎖的四個必要條件:互斥條件:一個資源每次只能被一個線程使用;請求與保持條件:一個線程因請求資源而阻塞時,對已獲得的資源保持不放;不剝奪條件:線程已獲得的資源,在末使用完之前,不能強行剝奪;循環(huán)等待條件:若干線程之間形成一種頭尾相接的循環(huán)等待資源關系;這四個條件是死鎖的必要條件,只要系統發(fā)生死鎖,這些條件必然成立,而只要上述條件之一不滿足,就不會發(fā)生死鎖。9.如何預防死鎖?答:預防死鎖的方法如下:盡量使用tryLock(longtimeout,TimeUnitunit)的方法(ReentrantLock、ReentrantReadWriteLock),設置超時時間,超時可以退出防止死鎖;盡量使用Java.util.concurrent并發(fā)類代替自己手寫鎖;盡量降低鎖的使用粒度,盡量不要幾個功能用同一把鎖;盡量減少同步的代碼塊。10.thread.wait()和thread.wait(0)有什么區(qū)別?代表什么含義?答:thread.wait()和thread.wait(0)是相同的,使用thread.wait()內部其實是調用的thread.wait(0),源碼如下:publicfinalvoidwait()throwsInterruptedException{

wait(0);

}wait()表示進入等待狀態(tài),釋放當前的鎖讓出CPU資源,并且只能等程序執(zhí)行notify()/notifyAll()方法才會被重寫喚醒。11.如何讓兩個程序依次輸出11/22/33等數字,請寫出實現代碼?答:使用思路是在每個線程輸出信息之后,讓當前線程等待一會再執(zhí)行下一次操作,具體實現代碼如下:newThread(()->{

for(inti=1;i<4;i++){

System.out.println("線程一:"+i);

try{

Thread.sleep(100);

}catch(InterruptedExceptione){

e.printStackTrace();

}

}

}).start();

newThread(()->{

for(inti=1;i<4;i++){

System.out.println("線程二:"+i);

try{

Thread.sleep(100);

}catch(InterruptedExceptione){

e.printStackTrace();

}

}

}).start();程序執(zhí)行結果如下:線程一:1線程二:1線程二:2線程一:2線程二:3線程一:312.說一下線程的調度策略?答:線程調度器選擇優(yōu)先級最高的線程運行,但是如果發(fā)生以下情況,就會終止線程的運行:線程體中調用了yield()方法,讓出了對CPU的占用權;線程體中調用了sleep()方法,使線程進入睡眠狀態(tài);線程由于I/O操作而受阻塞;另一個更高優(yōu)先級的線程出現;在支持時間片的系統中,該線程的時間片用完??偨Y程序的運行依靠的是進程,而進程的執(zhí)行依靠的是多個線程,多線程之間可以共享一塊內存和一組系統資源,而多進程間通常是相互獨立的。線程的創(chuàng)建有三種方式:繼承Thread重寫run方法,實現Runnable或Callable接口,其中Callable可以允許線程的執(zhí)行有返回值,JDK8中也可以使用Lambda來更加方便的使用線程,線程是有優(yōu)先級的,優(yōu)先級從1-10,數字越大優(yōu)先級越高,也越早被執(zhí)行。如果兩個線程各自擁有一把鎖的同時,又同時等待獲取對方的鎖,就會造成死鎖??梢越档玩i的粒度或減少同步代碼塊的范圍或使用Java提供的安全類,來防止死鎖的產生。 如何輕松獲得Offer你好,我是王磊,某上市公司技術研發(fā)經理,前奇虎360員工,有著10余年的編程工作經驗,目前主要負責新員工技術面試和構建企業(yè)技術架構的相關事宜。隨著面試過的人數增加,我發(fā)現面試者們暴露出了技術方面的很多問題,為了讓更多面試者少走一些彎路,也為了讓企業(yè)能招到合適的技術人才,于是就誕生了這個專欄。為了寫好這個專欄內容,我先后拜訪了一二十家互聯網公司,與不同的面試官和面試者進行面對面探討,深入了解了企業(yè)對于面試者的要求和常見的Java面試題型。之后我花了大半年的時間,結合自己4年多作為面試官的經歷,把這些內容整理成文,用大約10萬字的內容對Java的核心知識點和常見的500多道面試題,做了詳細的介紹,也就是本專欄中你所看到的全部內容,希望對你能有所幫助。為什么要學這個專欄內容?「因為它能為你贏得面試的主動權,讓你獲得更多的Offer?!箯臉I(yè)十多年,我從面試者變成面試官,在Java面試上積累了比較豐富的經驗。其實,很多面試者在搜集面試資料的時候都踩過一些“坑”,你是不是也遇到過:免費搜索的面試題,內容不全面,這就算了,有時候答案都不準確;很多培訓機構提供的面試寶典內容雖然不少,但深度不夠,且面試題過于老舊脫離了企業(yè)實際需要;還有很多付費的面試題存在濫竽充數,提供了很多沒有價值的面試題,錢花了,干貨沒學到;市面上大部分面試題只講了基礎概念,沒有提供題目解析和示例代碼,不利于讀者真正的掌握背后的原理,只能死記硬背,且容易忘記。為了規(guī)避這些“坑”,我跑了很多家互聯網公司,來確認Java面試中實際考察的高頻知識點和常見題型??墒怯辛说谝皇炙夭暮?,我要如何讓大家真正從我的講解中學到干貨、用到實處呢?經過反復驗證,我才設計了如下的內容講述模式。第一,500+面試題詳解。如果你是還沒走入職場的新人,我會為你提供完整的Java技術棧講解,以及最新、最全、最實用的500多道Java面試題詳解。第二,10萬字Java核心知識點梳理。本專欄的每一篇內容,都采用的是「核心知識點+N道相關面試題」的模式,讓你不單能應付面試,還能學到更多的Java核心知識。第三,技術、面試搭配平衡,不但讓你學到心里,還助你展示出來。面對目前技術市場的相對冷淡和一個職位多個應聘者競爭的現狀,面試者們只有掌握更多Java核心技能和面試理論知識,才能在眾多面試者中脫穎而出。本專欄每篇文章大致分為兩個部分:Java核心點介紹+相關面試題詳解,這兩部分內容相輔相成,前面的核心知識點介紹讓后面的面試題更容易理解,后面的面試題加深了讀者對于Java核心點的掌握。如此一來,讓你所學及所用,不僅能夠應付面試,更能學習到更多有價值的Java技術點,讓你在面試中和工作中都能展示的更加出色。專欄大綱本專欄分為七大部分,共計37講,約10萬字。第一部分:Java基礎強化這部分包含7篇文章,我會從Java最基礎的內容講起。有最常見的String面試題從表象到原理的深入講解;還有Java8中新特性的介紹,比如時間和日期模塊,讓你使用更簡潔和優(yōu)化的方式寫出更完美的代碼;還有我們日常用的很多包裝類不為人知的有趣現象和知識盲點介紹;還有數組以及算法的介紹,雖然基礎但容易被面試者忽略和容易出錯的問題……第二部分:各種類和克隆這部分包含4篇文章,除了會深入講解Java中的各種類和接口的相關內容,還會深入講解淺克隆和深克隆的各種實現方式,以及配合各

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論