1.如何實(shí)現(xiàn)list和數(shù)組相互轉(zhuǎn)化:
- 數(shù)組轉(zhuǎn)List
1).使用for循環(huán)將數(shù)組元素加入List中;
List<String> list=new ArrayList<String>();
for (String string : str) {
list.add(string);
}
2).使用asList()方法,注意:asList()返回的列表大小是固定的,并且不是java.util.ArrayList類(lèi),而是定義在java.util.Arrays中一個(gè)私有靜態(tài)類(lèi)java.util.Arrays.ArrayList,這種情況,如果添加或者刪除列表中的元素,程序會(huì)拋出異常
List<String> list3 = Arrays.asList(str);
3).使用Collections.addAll()
List<String> list4=new ArrayList<String>(str.length);
Collections.addAll(list4, str);
4).使用Stream中的Collector收集器
List<String> list5=Stream.of(str).collect(Collectors.toList());
- List轉(zhuǎn)數(shù)組
1).使用for循環(huán)
String[] str1=new String[list.size()];
for(int i=0;i<list.size();i++) {
str1[i]=list.get(i);
}
for (String string : str1) {
System.out.println(string);
}
2).使用toArray()
String[] str2=list.toArray(new String[list.size()]);
2.Array和ArrayList區(qū)別
- 存儲(chǔ)內(nèi)容:Array可以包含基本類(lèi)型和對(duì)象類(lèi)型,ArrayList只能包含對(duì)象類(lèi)型。注意:Array數(shù)組在存放的時(shí)候一定是同種類(lèi)型的元素;ArrayList就不一定了,因?yàn)锳rrayList可以存儲(chǔ)Object
- 空間大?。篈rray大小是固定的,ArrayList的大小是動(dòng)態(tài)變化的。
- 方法:ArrayList提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。
- 對(duì)于基本類(lèi)型數(shù)據(jù),集合使用自動(dòng)裝箱來(lái)減少編碼工作量。但是,當(dāng)處理固定大小的基本數(shù)據(jù)類(lèi)型的時(shí)候,這種方式相對(duì)比較慢。
- 基于效率和類(lèi)型檢驗(yàn),應(yīng)盡可能使用Array,無(wú)法確定數(shù)組大小時(shí)才使用ArrayList!不過(guò)當(dāng)你試著解決更一般化的問(wèn)題時(shí),Array的功能就可能過(guò)于受限。
3.迭代器Iterator
- 迭代其實(shí)我們可以簡(jiǎn)單地理解為遍歷,是一個(gè)標(biāo)準(zhǔn)化遍歷各類(lèi)容器里面的所有對(duì)象的方法類(lèi),它是一個(gè)很典型的設(shè)計(jì)模式。Iterator模式是用于遍歷集合類(lèi)的標(biāo)準(zhǔn)訪(fǎng)問(wèn)方法。它可以把訪(fǎng)問(wèn)邏輯從不同類(lèi)型的集合類(lèi)中抽象出來(lái),從而避免向客戶(hù)端暴露集合的內(nèi)部結(jié)構(gòu)。
4.并發(fā)和并行的區(qū)別
- 并發(fā)(Concurrent),在操作系統(tǒng)中,是指一個(gè)時(shí)間段中有幾個(gè)程序都處于已啟動(dòng)運(yùn)行到運(yùn)行完畢之間,且這幾個(gè)程序都是在同一個(gè)處理機(jī)上運(yùn)行。
- 并行(Parallel),當(dāng)系統(tǒng)有一個(gè)以上CPU時(shí),當(dāng)一個(gè)CPU執(zhí)行一個(gè)進(jìn)程時(shí),另一個(gè)CPU可以執(zhí)行另一個(gè)進(jìn)程,兩個(gè)進(jìn)程互不搶占CPU資源,可以同時(shí)進(jìn)行,這種方式我們稱(chēng)之為并行(Parallel)。
- 并發(fā)是指在一段時(shí)間內(nèi)宏觀(guān)上多個(gè)程序同時(shí)運(yùn)行。并行指的是同一個(gè)時(shí)刻,多個(gè)任務(wù)確實(shí)真的在同時(shí)運(yùn)行。
- 并發(fā)的多個(gè)任務(wù)之間是互相搶占資源的;并行的多個(gè)任務(wù)之間是不互相搶占資源的。
5.線(xiàn)程與進(jìn)程的區(qū)別
- 進(jìn)程:是執(zhí)行中一段程序,即一旦程序被載入到內(nèi)存中并準(zhǔn)備執(zhí)行,它就是一個(gè)進(jìn)程。進(jìn)程是表示資源分配的的基本概念,又是調(diào)度運(yùn)行的基本單位,是系統(tǒng)中的并發(fā)執(zhí)行的單位。
- 線(xiàn)程:?jiǎn)蝹€(gè)進(jìn)程中執(zhí)行中每個(gè)任務(wù)就是一個(gè)線(xiàn)程。線(xiàn)程是進(jìn)程中執(zhí)行運(yùn)算的最小單位。
- 一個(gè)線(xiàn)程只能屬于一個(gè)進(jìn)程,但是一個(gè)進(jìn)程可以擁有多個(gè)線(xiàn)程。多線(xiàn)程處理就是允許一個(gè)進(jìn)程中在同一時(shí)刻執(zhí)行多個(gè)任務(wù)。
6.守護(hù)線(xiàn)程(Daemon Thread)
- 只要當(dāng)前JVM實(shí)例中尚存在任何一個(gè)非守護(hù)線(xiàn)程沒(méi)有結(jié)束,守護(hù)線(xiàn)程就全部工作;只有當(dāng)最后一個(gè)非守護(hù)線(xiàn)程結(jié)束時(shí),守護(hù)線(xiàn)程隨著JVM一同結(jié)束工作。
- Daemon的作用是為其他線(xiàn)程的運(yùn)行提供便利服務(wù),守護(hù)線(xiàn)程最典型的應(yīng)用就是 GC (垃圾回收器),它就是一個(gè)很稱(chēng)職的守護(hù)者。
7.線(xiàn)程有哪些方式
新建(NEW):新創(chuàng)建一個(gè)線(xiàn)程對(duì)象
-
就緒:一個(gè)新創(chuàng)建的線(xiàn)程并不自動(dòng)開(kāi)始運(yùn)行,要執(zhí)行線(xiàn)程,必須調(diào)用線(xiàn)程的start()方法。當(dāng)線(xiàn)程對(duì)象調(diào)用start()方法即啟動(dòng)了線(xiàn)程,start()方法創(chuàng)建線(xiàn)程運(yùn)行的系統(tǒng)資源,并調(diào)度線(xiàn)程運(yùn)行run()方法。當(dāng)start()方法返回后,線(xiàn)程就處于就緒狀態(tài)。
處于就緒狀態(tài)的線(xiàn)程并不一定立即運(yùn)行run()方法,線(xiàn)程還必須同其他線(xiàn)程競(jìng)爭(zhēng)CPU時(shí)間,只有獲得CPU時(shí)間才可以運(yùn)行線(xiàn)程。因?yàn)樵趩蜟PU的計(jì)算機(jī)系統(tǒng)中,不可能同時(shí)運(yùn)行多個(gè)線(xiàn)程,一個(gè)時(shí)刻僅有一個(gè)線(xiàn)程處于運(yùn)行狀態(tài)。因此此時(shí)可能有多個(gè)線(xiàn)程處于就緒狀態(tài)。對(duì)多個(gè)處于就緒狀態(tài)的線(xiàn)程是由Java運(yùn)行時(shí)系統(tǒng)的線(xiàn)程調(diào)度程序來(lái)調(diào)度的。
運(yùn)行狀態(tài)(running):當(dāng)線(xiàn)程獲得CPU時(shí)間后,它才進(jìn)入運(yùn)行狀態(tài),真正開(kāi)始執(zhí)行run()方法。
-
阻塞狀態(tài)(blocked):線(xiàn)程運(yùn)行過(guò)程中,可能由于各種原因進(jìn)入阻塞狀態(tài):
①線(xiàn)程通過(guò)調(diào)用sleep方法進(jìn)入睡眠狀態(tài);
②線(xiàn)程調(diào)用一個(gè)在I/O上被阻塞的操作,即該操作在輸入輸出操作完成之前不會(huì)返回到它的調(diào)用者;
③線(xiàn)程試圖得到一個(gè)鎖,而該鎖正被其他線(xiàn)程持有;
④線(xiàn)程在等待某個(gè)觸發(fā)條件;
所謂阻塞狀態(tài)是正在運(yùn)行的線(xiàn)程沒(méi)有運(yùn)行結(jié)束,暫時(shí)讓出CPU,這時(shí)其他處于就緒狀態(tài)的線(xiàn)程就可以獲得CPU時(shí)間,進(jìn)入運(yùn)行狀態(tài)。
-
死亡狀態(tài)(dead):有兩個(gè)原因會(huì)導(dǎo)致線(xiàn)程死亡:
①run方法正常退出而自然死亡;
②一個(gè)未捕獲的異常終止了run方法而使線(xiàn)程猝死;
為了確定線(xiàn)程在當(dāng)前是否存活著(就是要么是可運(yùn)行的,要么是被阻塞了),需要使用isAlive方法,如果是可運(yùn)行或被阻塞,這個(gè)方法返回true;如果線(xiàn)程仍舊是new狀態(tài)且不是可運(yùn)行的,或者線(xiàn)程死亡了,則返回false。
image.png
8.sleep()和wait()的區(qū)別
- sleep() 方法是線(xiàn)程類(lèi)(Thread)的靜態(tài)方法,讓調(diào)用線(xiàn)程進(jìn)入睡眠狀態(tài),讓出執(zhí)行機(jī)會(huì)給其他線(xiàn)程,等到休眠時(shí)間結(jié)束后,線(xiàn)程進(jìn)入就緒狀態(tài)和其他線(xiàn)程一起競(jìng)爭(zhēng)cpu的執(zhí)行時(shí)間。
因?yàn)閟leep() 是static靜態(tài)的方法,他不能改變對(duì)象的機(jī)鎖,當(dāng)一個(gè)synchronized塊中調(diào)用了sleep() 方法,線(xiàn)程雖然進(jìn)入休眠,但是對(duì)象的機(jī)鎖沒(méi)有被釋放,其他線(xiàn)程依然無(wú)法訪(fǎng)問(wèn)這個(gè)對(duì)象
sleep可以在任何地方使用 - wait()是Object類(lèi)的方法,當(dāng)一個(gè)線(xiàn)程執(zhí)行到wait方法時(shí),它就進(jìn)入到一個(gè)和該對(duì)象相關(guān)的等待池,同時(shí)釋放對(duì)象的機(jī)鎖,使得其他線(xiàn)程能夠訪(fǎng)問(wèn),可以通過(guò)notify,notifyAll方法來(lái)喚醒等待的線(xiàn)程
wait只能在同步控制方法或者同步控制塊里面使用
9.notify和notifyAll區(qū)別
- 鎖池和等待池
鎖池:假設(shè)線(xiàn)程a已經(jīng)擁有某個(gè)對(duì)象的鎖,而其他的線(xiàn)程想要調(diào)用這個(gè)對(duì)象的某個(gè)synchronized方法(或者synchronized塊),由于這些線(xiàn)程在進(jìn)入對(duì)象的synchronized方法之前必須獲得該對(duì)象的鎖的擁有權(quán),但是該對(duì)象的鎖目前正被線(xiàn)程a所擁有,所以這些線(xiàn)程就進(jìn)入了該對(duì)象的鎖池中
等待池:假設(shè)一個(gè)線(xiàn)程a調(diào)用了某個(gè)對(duì)象的wait()方法,線(xiàn)程a就會(huì)釋放giant對(duì)象的鎖后,進(jìn)入到該對(duì)象的等待池中,等待池中的線(xiàn)程不會(huì)去競(jìng)爭(zhēng)該對(duì)象的鎖 - 區(qū)別:當(dāng)有線(xiàn)程調(diào)用了該對(duì)象的notifyAll()方法(該方法喚醒所有wait線(xiàn)程)或者notify()方法(只隨機(jī)喚醒一個(gè)wait線(xiàn)程),被喚醒的線(xiàn)程就會(huì)進(jìn)入該對(duì)象的鎖池中,鎖池中的線(xiàn)程就會(huì)競(jìng)爭(zhēng)該對(duì)象鎖。即調(diào)用了notify后只有一個(gè)線(xiàn)程會(huì)由等待池進(jìn)入鎖池,而notifyAll會(huì)將該對(duì)象等待池中所有線(xiàn)程移動(dòng)到鎖池中,等待鎖競(jìng)爭(zhēng)
- 永遠(yuǎn)在循環(huán)(loop)里調(diào)用 wait 和 notify,不是在 If 語(yǔ)句
10.java創(chuàng)建線(xiàn)程池的方式
- Executors目前提供了5種不同的線(xiàn)程池配置
- 1.newCachedThreadPool(),它是用來(lái)處理大量短時(shí)間工作任務(wù)的線(xiàn)程池,具有幾個(gè)鮮明特點(diǎn):它會(huì)試圖緩存線(xiàn)程并重用,當(dāng)無(wú)緩存線(xiàn)程可用時(shí),就會(huì)創(chuàng)建新的工作線(xiàn)程;如果線(xiàn)程閑置時(shí)間超過(guò)60秒,則被終止并移除緩存;長(zhǎng)時(shí)間閑置時(shí),這種線(xiàn)程池,不會(huì)消耗什么資源。其內(nèi)部使用SynchronousQueue作為工作隊(duì)列。
- 2.newFixedThreadPool(int nThreads),重用指定數(shù)目(nThreads)的線(xiàn)程,其背后使用的是無(wú)界的工作隊(duì)列,任何時(shí)候最多有nThreads個(gè)工作線(xiàn)程是活動(dòng)的。這意味著,如果任務(wù)數(shù)量超過(guò)了活動(dòng)線(xiàn)程數(shù)目,將在工作隊(duì)列中等待空閑線(xiàn)程出現(xiàn);如果工作線(xiàn)程退出,將會(huì)有新的工作線(xiàn)程被創(chuàng)建,以補(bǔ)足指定數(shù)目nThreads。
- 3.newSingleThreadExecutor(),它的特點(diǎn)在于工作線(xiàn)程數(shù)目限制為1,操作一個(gè)無(wú)界的工作隊(duì)列,所以它保證了所有的任務(wù)都是被順序執(zhí)行,最多會(huì)有一個(gè)任務(wù)處于活動(dòng)狀態(tài),并且不予許使用者改動(dòng)線(xiàn)程池實(shí)例,因此可以避免改變線(xiàn)程數(shù)目。
- 4.newSingleThreadScheduledExecutor()和newScheduledThreadPool(int corePoolSize),創(chuàng)建的是個(gè)ScheduledExecutorService,可以進(jìn)行定時(shí)或周期性的工作調(diào)度,區(qū)別在于單一工作線(xiàn)程還是多個(gè)工作線(xiàn)程。
- 5.newWorkStealingPool(int parallelism),這是一個(gè)經(jīng)常被人忽略的線(xiàn)程池,Java 8 才加入這個(gè)創(chuàng)建方法,其內(nèi)部會(huì)構(gòu)建ForkJoinPool,利用Work-Stealing算法,并行地處理任務(wù),不保證處理順序。
