Q:什么是線程错邦?什么是進(jìn)程腻豌?線程和進(jìn)程有什么區(qū)別家坎?
A:線程:又稱"輕量級進(jìn)程",是操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度的最小單位吝梅,被包含在進(jìn)程之中虱疏,是進(jìn)程中的實(shí)際運(yùn)作單位。
進(jìn)程: 系統(tǒng)進(jìn)行資源分配和調(diào)度的基本單位苏携。
兩者之間的區(qū)別:
地址空間和其他資源:進(jìn)程間相互獨(dú)立做瞪,同一進(jìn)程的各線程間共享,某進(jìn)程中的線程在其他進(jìn)程不可見。
通信:進(jìn)程間通信 IPC装蓬,線程間可以直接讀寫進(jìn)程數(shù)據(jù)段(如全局變量)來進(jìn)行通信——需要進(jìn)程同步和互斥手段的輔助著拭,以保證數(shù)據(jù)的一致性。
調(diào)度和切換:線程上下文切換比進(jìn)程上下文切換要快得多牍帚。
在多線程 OS 中儡遮,進(jìn)程不是一個可執(zhí)行的實(shí)體。
Q:多線程編程的好處是什么暗赶?
A:發(fā)揮多核 CPU 的優(yōu)勢(提高性能)鄙币、防止阻塞、便于建模蹂随。
Q:有幾種創(chuàng)建線程的方式十嘿?哪種比較好?
A:①岳锁、實(shí)現(xiàn) Runnable 接口(較好:靈活绩衷,減少耦合度);②激率、繼承 Thread 類唇聘。
Q:Runnable 接口和 Callable 接口的區(qū)別?
A:Callable 接口中的 call() 方法是可以返回值和拋出異常柱搜,是一個泛型迟郎,和 Future / FutureTask 配合來獲取結(jié)果。而 Runnalbe 接口的 run() 方法聪蘸,無返回值宪肖。
Q:Java 中 CyclicBarrier 和 CountDownLatch 有什么不同?
A:①健爬、CyclicBarrier 是 n 個線程控乾,相互等待;CountDownLatch 是一個或多個線程娜遵,等待另外 n 個線程執(zhí)行完蜕衡,再執(zhí)行。
②设拟、CyclicBarrier 加計(jì)數(shù)慨仿;CountDownLatch 減計(jì)數(shù)。
③纳胧、CyclicBarrier 計(jì)數(shù)達(dá)到指定值時镰吆,計(jì)數(shù)置為 0 重新開始;CountDownLatch 計(jì)數(shù)為 0 時跑慕,無法重置万皿。(不可重復(fù)利用)
④摧找、CyclicBarrier 調(diào)用 await() 方法計(jì)數(shù)加 1 , 若加 1 后的值不等于構(gòu)造方法的值牢硅,則線程阻塞蹬耘;CountDownLatch 調(diào)用 countDown() 方法計(jì)數(shù)減 1 ,調(diào)用 await() 方法只進(jìn)行阻塞减余,對計(jì)數(shù)沒任何影響综苔。
Q:volatile 是什么?作用是什么佳励?
A:volatile 是一個類型修飾符休里,是用來修飾被不同線程訪問和修改的變量蛆挫。
主要作用有兩個:①赃承、內(nèi)存可見性,即線程 A 對 volatile 變量的修改悴侵,其他線程獲取的 volatile 變量都是最新的瞧剖;②、可以禁止指令(程序執(zhí)行的順序)重排序可免。
Q:什么是線程安全抓于?
A:線程安全:多線程訪問時,采用了加鎖機(jī)制浇借,當(dāng)一個數(shù)據(jù)訪問該類的某個數(shù)據(jù)時捉撮,進(jìn)行保護(hù),其他線程不能進(jìn)行訪問直到該線程讀取完妇垢,其他線程才可使用巾遭。不會出現(xiàn)數(shù)據(jù)不一致或者數(shù)據(jù)污染。
線程不安全:不提供數(shù)據(jù)訪問保護(hù)闯估,有可能多個線程先后更改數(shù)據(jù)造成所得到的數(shù)據(jù)是臟數(shù)據(jù)灼舍。
Q:線程安全分為哪幾種級別?
A:①涨薪、不可變:不變的對象絕對是線程安全的骑素,不需要線程同步,如 String刚夺、Long献丑、BigInteger;
②侠姑、無條件的線程安全:對象自身做了足夠多的內(nèi)部同步阳距,也不需要外部同步,如 Random结借、ConcurrentHahsMap筐摘、Concurrent 集合、atomic;
③咖熟、有條件的線程安全:對象的部分方法可以無條件安全使用圃酵,但是有些地方需要外部同步,需要 Collectiongs.synchronized馍管;有條件線程安全的最常見的例子是遍歷由 HashTable 或者 Vector 或者返回的迭代器郭赐;
④、非線程安全(線程兼容):對象本身不提供線程安全機(jī)制确沸,但是通過外部同步捌锭,可以在并發(fā)環(huán)境使用,如 ArrayList罗捎、HashMap观谦;
⑤、線程對立:即使外部進(jìn)行了同步調(diào)用桨菜,也不能保證線程安全豁状,這種情況非常少,如 System.setOut()倒得、System.runFinalizersOnExit()泻红。
Q:如何正確地停止一個線程?
A:①霞掺、使用退出標(biāo)志谊路,使線程正常退出,也就是當(dāng) run 方法完成后線程終止菩彬;
②缠劝、使用 interrupt 方法中斷線程;
③挤巡、使用 stop 方法強(qiáng)行終止剩彬,但是不推薦使用,因?yàn)?stop 和 suspend 以及 resume 一樣存在死鎖威脅矿卑,并且都是過期作廢的方法喉恋。
Q:一個線程運(yùn)行時發(fā)生異常會怎樣?
A:①母廷、如果異常沒有被捕獲轻黑,該線程將會停止執(zhí)行。
②琴昆、如果這個線程持有某個對象的監(jiān)視器氓鄙,那么這個對象監(jiān)視器會被立即釋放。
Q:兩個線程之間业舍,如何實(shí)現(xiàn)數(shù)據(jù)共享抖拦?
A:①升酣、使用同一個 Runnable 對象;
②态罪、使用不同的 Runnable 對象:
i噩茄、將共享數(shù)據(jù)分別傳遞給兩個不同的線程;
ii复颈、將這些 Runnable 對象作為一個內(nèi)部類绩聘,將共享數(shù)據(jù)作為成員變量。
Q:sleep() 方法和 wait() 方法有什么區(qū)別耗啦?
A:①凿菩、所在的類:sleep 在 Thread 類中、wait 在 Object 類中帜讲;
②衅谷、鎖:sleep 方法沒有釋放鎖、wait 方法釋放了鎖舒帮;
③会喝、使用范圍:sleep 可以在任何地方使用陡叠、而 wait玩郊,notify 和 notifyAll 只能在同步控制方法或者同步控制塊里面使用。
Q:ThreadLoacl 是什么枉阵?作用是什么译红?
A:它是線程局部變量,每個線程都有自己的 ThreadLocal兴溜。
作用:把數(shù)據(jù)進(jìn)行隔離侦厚,數(shù)據(jù)不共享(空間換時間,在 Thread 中維護(hù)了一個以開地址法實(shí)現(xiàn)的 ThreadLocalMap )拙徽。
Q:為什么 wait() 方法和 notify()/notifyAll() 方法要在同步塊( synchronized )中被調(diào)用刨沦?
A:JDK 強(qiáng)制的,方法調(diào)用之前必須先獲得對象的鎖膘怕。如果不這樣做想诅,就會拋出 IllegalMonitorStateException 異常。
Q:同步集合 & 并發(fā)集合的區(qū)別岛心?
A:都支持線程安全来破,主要區(qū)別體現(xiàn)在性能和可擴(kuò)展性。
性能:同步集合會把整個 Map 或者 List 鎖起來忘古,而并發(fā)集合不會徘禁。所以同步集合比并發(fā)集合慢的多。
可擴(kuò)展性:并發(fā)集合不僅提供線程安全髓堪,還用鎖分離和內(nèi)部分區(qū)等現(xiàn)代技術(shù)來提高可擴(kuò)展性送朱。
Q:什么是線程池娘荡? 為什么要使用它?
A:在程序啟動時驶沼,就創(chuàng)建若干個線程來響應(yīng)請求它改。使用它,可以避免頻繁地創(chuàng)建和銷毀線程商乎,達(dá)到線程對象的重用央拖,還可以根據(jù)項(xiàng)目靈活地控制并發(fā)的數(shù)目。
Q:什么是死鎖鹉戚?死鎖發(fā)生的必要條件鲜戒?如何避免死鎖?
A:死鎖:兩個及以上的進(jìn)程在執(zhí)行過程中抹凳,因爭奪資源而造成的一種互相等待的現(xiàn)象遏餐,若無外力作用,他們都將無法推進(jìn)下去赢底。
死鎖的必要條件:
①失都、互斥條件:一個資源每次只能被一個進(jìn)程使用;
②幸冻、請求與保持條件:一個進(jìn)程因請求資源而阻塞時粹庞,對已獲得的資源保持不變;
③洽损、不剝奪條件:進(jìn)程已獲得的資源庞溜,在未使用之前,不能強(qiáng)行剝奪碑定;
④流码、循環(huán)等待條件:若干進(jìn)程之間形成一種頭尾相連的循環(huán)等待資源關(guān)系。避免死鎖最簡單的方法:阻止循環(huán)等待條件延刘,將系統(tǒng)中所有的資源設(shè)置標(biāo)志位漫试、排序,規(guī)定所有的進(jìn)程申請資源必須以一定的順序做操作碘赖。
Q:活鎖 & 死鎖的區(qū)別驾荣?
A:活鎖進(jìn)程的狀態(tài)可以改變但是卻不能繼續(xù)執(zhí)行。
Q:怎么檢測一個線程是否擁有鎖崖疤?
A:Thread 中的 holdsLock() 方法:如果當(dāng)且僅當(dāng)當(dāng)前線程擁有某個具體對象的鎖時秘车,返回 true。
Q:synchronized & ReentrantLock 的區(qū)別劫哼?
A:兩者都是加鎖方式同步(阻塞式同步)叮趴。
其本質(zhì)上的區(qū)別:synchronized 是關(guān)鍵字,ReentrantLock 是類权烧。
相對于 synchronized 而言眯亦,ReentrantLock 類提供了一些高級功能:
①伤溉、等待可中斷:持有鎖的線程長期不釋放時,正在等待的線程可以選擇放棄等待妻率,這相等于 synchronized 來說乱顾,避免了死鎖砾淌;
②乞巧、公平鎖:synchronized 只能是非公平鎖,ReenTrantLock 可以通過構(gòu)造函數(shù)的參數(shù)來指定公平鎖和非公平鎖邮旷。(公平鎖:先等待的線程先得到鎖)孤里;
③伏伯、鎖綁定多個條件:一個 ReentrantLock 對象可以同時綁定多個對象。
④捌袜、鎖機(jī)制不一樣:synchronized
Q:如何保證線程按照指定順序執(zhí)行说搅?
A:使用 new Thread().join() 方法:等待線程結(jié)束。也就是說通過一個線程等待另一個線程執(zhí)行完畢虏等,再繼續(xù)執(zhí)行弄唧,來實(shí)現(xiàn)。
Q:如果你提交任務(wù)時霍衫,線程池隊(duì)列已滿候引。會時發(fā)會生什么?
A:當(dāng)一個任務(wù)不能被調(diào)度執(zhí)行時慕淡,ThreadPoolExecutor 的 submit() 方法將會拋出 RejectedExecutionException 異常背伴。
Q:Java 線程池中 submit() & execute() 方法有什么區(qū)別沸毁?
A:①峰髓、接收的參數(shù)不一樣;②息尺、submit() 有返回值携兵,execute() 沒有
;③搂誉、submit() 方便 Exception 處理徐紧。
Q:ReadWriteLock 是什么?
A:維護(hù)一對關(guān)聯(lián)的鎖炭懊,一個用于只讀操作并级,一個用于寫操作。讀鎖是共享的侮腹,而寫鎖是獨(dú)占的嘲碧。
Q:多線程中的忙循環(huán)是什么?使用它的目的是什么父阻?
A:忙循環(huán):用循環(huán)讓一個線程等待愈涩,不會放棄 CPU望抽。
目的:為了保留 CPU 緩存,避免重建緩存和減少等待重建時間履婉。在多核系統(tǒng)中煤篙,一個等待線程醒來時,可能會在另一個內(nèi)核運(yùn)行毁腿,這樣就會重建緩存辑奈。
Q:遵循的多線程的最佳實(shí)踐有哪幾條?
A:①已烤、給線程起一個有意義的名字身害;②、避免鎖定和縮小同步的范圍草戈;③塌鸯、多用同步類,少用 wait 和 notify唐片;④丙猬、多用并發(fā)集合,少用同步集合费韭。
Q:如何強(qiáng)制啟動一個線程茧球?
A:它是被線程調(diào)度器控制的,并且 Java 沒有公布相關(guān)的 API星持。
Q:fork-join 框架是什么抢埋?
A:Java7 提供了的一個用于并行執(zhí)行任務(wù)的框架, 是一個把大任務(wù)分割成若干個小任務(wù)督暂,最終匯總每個小任務(wù)結(jié)果后得到大任務(wù)結(jié)果的框架揪垄。使用了工作竊取算法。