java開發師筆試面試每日12題(2)
1.Volatile和Synchronized不同點
(1)、volatile只能作用於變量,使用範圍較小。synchronized可以用在變量、方法、類、同步代碼塊等,使用範圍比較廣。
(2)、volatile只能保證可見性和有序性,不能保證原子性。而可見性、有序性、原子性synchronized都可以包證。
(3)、volatile不會造成線程阻塞。synchronized可能會造成線程阻塞。
java多線程中的原子性、可見性、有序性
(1)、原子性:是指線程的多個操作是一個整體,不能被分割,要麽就不執行,要麽就全部執行完,中間不能被打斷。
(2)、可見性:是指線程之間的可見性,就是一個線程修改後的結果,其他的線程能夠立馬知道。
(3)、有序性:為了提高執行效率,java中的編譯器和處理器可以對指令進行重新排序,重新排序會影響多線程並發的正確性,有序性就是要保證不進行重新排序(保證線程操作的執行順序)。
volatile關鍵字的作用
其實volatile關鍵字的作用就是保證了可見性和有序性(不保證原子性),如果一個共享變量被volatile關鍵字修飾,那麽如果一個線程修改了這個共享變量後,其他線程是立馬可知的。為什麽是這樣的呢?比如,線程A修改了自己的共享變量副本,這時如果該共享變量沒有被volatile修飾,那麽本次修改不一定會馬上將修改結果刷新到主存中,如果此時B去主存中讀取共享變量的值,那麽這個值就是沒有被A修改之前的值。如果該共享變量被volatile修飾了,那麽本次修改結果會強制立刻刷新到主存中,如果此時B去主存中讀取共享變量的值,那麽這個值就是被A修改之後的值了。
volatile能禁止指令重新排序,在指令重排序優化時,在volatile變量之前的指令不能在volatile之後執行,在volatile之後的指令也不能在volatile之前執行,所以它保證了有序性。
synchronized關鍵字的作用
synchronized提供了同步鎖的概念,被synchronized修飾的代碼段可以防止被多個線程同時執行,必須一個線程把synchronized修飾的代碼段都執行完畢了,其他的線程才能開始執行這段代碼。
因為synchronized保證了在同一時刻,只能有一個線程執行同步代碼塊,所以執行同步代碼塊的時候相當於是單線程操作了,那麽線程的可見性、原子性、有序性(線程之間的執行順序)它都能保證了。
2.Java的數據結構有那些
①數組 (Array)
在程序設計中,為了處理方便, 把具有相同類型的若幹變量按有序的形式組織起來。這些按序排列的同類數
據元素的集合稱為數組。在C語言中, 數組屬於構造數據類型。一個數組可以分解為多個數組元素,這些數組
元素可以是基本數據類型或是構造類型。因此按數組元素的類型不同,數組又可分為數值數組、字符數組、指
針數組、結構數組等各種類別。
②棧 (Stack)
棧是只能在某一端插入和刪除的特殊線性表。它按照先進後出的原則存儲數據,先進入的數據被壓入棧底,最後
的數據在棧頂,需要讀數據的時候從棧頂開始彈出數據(最後一個數據被第一個讀出來)。
③隊列 (Queue)
一種特殊的線性表,它只允許在表的前端(front)進行刪除操作,而在表的後端(rear)進行插入操作。進行
插入操作的端稱為隊尾,進行刪除操作的端稱為隊頭。隊列中沒有元素時,稱為空隊列。
④鏈表 (Linked List)
一種物理存儲單元上非連續、非順序的存儲結構,數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現的。
鏈表由一系列結點(鏈表中每一個元素稱為結點)組成,結點可以在運行時動態生成。每個結點包括兩個部分:
一個是存儲數據元素的數據域,另一個是存儲下一個結點地址的指針域。
⑤樹 (Tree)
樹是包含n(n>0)個結點的有窮集合K,且在K中定義了一個關系N,N滿足 以下條件:
(1)有且僅有一個結點 k0,他對於關系N來說沒有前驅,稱K0為樹的根結點。簡稱為根(root)
(2)除K0外,k中的每個結點,對於關系N來說有且僅有一個前驅。
(3)K中各結點,對關系N來說可以有m個後繼(m>=0)。
⑥堆 (Heap)
在計算機科學中,堆是一種特殊的樹形數據結構,每個結點都有一個值。通常我們所說的堆的數據結構,是指
二叉堆。堆的特點是根結點的值最小(或最大),且根結點的兩個子樹也是一個堆。
⑦圖 (Graph)
圖是由結點的有窮集合V和邊的集合E組成。其中,為了與樹形結構加以區別,在圖結構中常常將結點稱為頂點,
邊是頂點的有序偶對,若兩個頂點之間存在一條邊,就表示這兩個頂點具有相鄰關系。
⑧散列表 (Hash)
若結構中存在關鍵字和K相等的記錄,則必定在f(K)的存儲位置上。由此,不需比較便可直接取得所查記錄。稱
這個對應關系f為散列函數(Hash function),按這個思想建立的表為散列表。
3.java中的繼承是單繼承還是多繼承
多繼承雖然能使子類同時擁有多個父類的特征,但是其缺點也是很顯著的,主要有兩方面:
(1)如果在一個子類繼承的多個父類中擁有相同名字的實例變量,子類在引用該變量時將產生歧義,無法判斷應該使用哪個父類的變量
(2)如果在一個子類繼承的多個父類中擁有相同方法,子類中有沒有覆蓋該方法,那麽調用該方法時將產生歧義,無法判斷應該調用哪個父類的方法
正因為有以上的致命缺點,所以java中禁止一個類繼承多個父類。單繼承就是摒棄了以上兩點。
4.a=a+b與a+=b有什麽區別嗎
在兩個變量的數據類型一樣時:a+=b 和a=a+b 是沒有區別的。
但是當兩個變量的數據類型不同時,就需要考慮一下數據類型自動轉換的問題了。也就是涉及到精度了。
“+=”是java中的一個運算符,而不是兩個,所以在運算時 會進行自動類型轉換,也就是低級變量可以直接轉換為高級變量。
5. 簡述synchronized和java.util.concurrent.locks.Lock的異同 ?
主要相同點:Lock能完成synchronized所實現的所有功能
主要不同點:Lock有比synchronized更精確的線程語義和更好的性能。synchronized會自動釋放鎖,而Lock一定要求程序員手工釋放,並且必須在finally從句中釋放。Lock還有更強大的功能,
例如,它的tryLock方法可以非阻塞方式去拿鎖
6.什麽是主鍵,什麽是外鍵
主鍵等於唯一約束和非空約束 外鍵用於在兩表之間建立關系,需要指定引用主表的那一列
(1)外鍵必須是主鍵的子集(2)刪除先刪外鍵再刪主鍵
7.講講類的實例化順序,比如父類靜態數據,構造函數,字段,子類靜態數據,構造函數,字段,當 new 的時候, 他們的執行順序
父類靜態代變量、
父類靜態代碼塊、
子類靜態變量、
子類靜態代碼塊、
父類非靜態變量(父類實例成員變量)、
父類構造函數、
子類非靜態變量(子類實例成員變量)、
子類構造函數。
先靜態、先父後子。
先靜態:父靜態 > 子靜態
優先級:父類 > 子類 靜態代碼塊 > 非靜態代碼塊 > 構造函數
一個類的實例化過程:
1,父類中的static代碼塊,當前類的static
2,順序執行父類的普通代碼塊
3,父類的構造函數
4,子類普通代碼塊
5,子類(當前類)的構造函數,按順序執行。
6,子類方法的執行,
8.什麽是值傳遞和引用傳遞
值傳遞:(形式參數類型是基本數據類型):方法調用時,實際參數把它的值傳遞給對應的形式參數,形式參數只是用實際參數的值初始化自己的存儲單元內容,是兩個不同的存儲單元,所以方法執行中形式參數值的改變不影響實際參數的值。
引用傳遞:(形式參數類型是引用數據類型參數):也稱為傳地址。方法調用時,實際參數是對象(或數組),這時實際參數與形式參數指向同一個地址,在方法執行中,對形式參數的操作實際上就是對實際參數的操作,這個結果在方法結束後被保留了下來,所以方法執行中形式參數的改變將會影響實際參數。
9.多線程的幾種實現方式
1、繼承Thread類創建線程
2、實現Runnable接口創建線程
3、實現Callable接口通過FutureTask包裝器來創建Thread線程
Callable<V> oneCallable = new SomeCallable<V>();
//由Callable<Integer>創建一個FutureTask<Integer>對象:
FutureTask<V> oneTask = new FutureTask<V>(oneCallable);
//註釋:FutureTask<Integer>是一個包裝器,它通過接受Callable<Integer>來創建,它同時實現了Future和Runnable接口。
//由FutureTask<Integer>創建一個Thread對象:
Thread oneThread = new Thread(oneTask);
oneThread.start();
//至此,一個線程就創建完成了。
4、使用ExecutorService、Callable、Future實現有返回結果的線程
ExecutorService、Callable、Future三個接口實際上都是屬於Executor框架。返回結果的線程是在JDK1.5中引入的新特征,有了這種特征就不需要再為了得到返回值而大費周折了。而且自己實現了也可能漏洞百出。
可返回值的任務必須實現Callable接口。類似的,無返回值的任務必須實現Runnable接口。
執行Callable任務後,可以獲取一個Future的對象,在該對象上調用get就可以獲取到Callable任務返回的Object了。
註意:get方法是阻塞的,即:線程無返回結果,get方法會一直等待。
再結合線程池接口ExecutorService就可以實現傳說中有返回結果的多線程了。
10.數組(Array)和列表(ArrayList)有什麽區別?什麽時候應該使用Array而不是ArrayList?
Array 可以包含基本類型和對象類型,ArrayList 只能包含對象類型。Array 大小是固定的,ArrayList 的大小是動態變化的。ArrayList 提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。對於基本類型數據,集合使用自動裝箱來減少編碼工作量。但是,當處理固定大小的基本數據類型的時候,這種方式相對比較慢。
當能確定長度並且數據類型一致的時候就可以用數組,其他時候使用ArrayList
java開發師筆試面試每日12題(2)