JAVA就業面試題
4.1單例模式java
單例,就是整個程序有且僅有一個實例。該類負責建立本身的對象,同時確保只有一個對象被建立。
特色面試
持有本身類型的屬性
類構造器私有
對外提供獲取實例的靜態方法
4.1.1 懶漢式安全
/**多線程
- Created by 張晨光 on 2020/6/12 11:07
- 懶漢式
*/
public class Banzhang {
//1.本身類的靜態屬性
private static Banzhang bz;
//2.私有的構造方法
private Banzhang(){}
//3.提供對外獲取實例的靜態方法
public static Banzhang getInstance(){
if(bz==null)
bz= new Banzhang();
return bz;
}
}
問題,線程不安全,延遲初始化,問題在 12行;
4.1.2 餓漢式ide
線程安全,比較經常使用,但容易產生垃圾,由於一開始就初始化測試
/**線程
- Created by 張晨光 on 2020/6/12 11:12
- 餓漢式
*/
public class SingleTon {
//1.靜態本身自己屬性;
private static SingleTon singleTon=new SingleTon();
//2.私有構造方法;
private SingleTon(){}
//3.提供靜態的方法實例;
public static SingleTon getInstance(){
return singleTon;
}
}
餓漢式:當即加載;code
懶漢式:延遲加載;–》節省資源
4.1.3 雙重鎖模式對象
雙重檢查模式,進行了兩次的判斷,第一次是爲了不不要的實例,第二次是爲了進行同步,避免多線程問題。因爲singleton=new Singleton()對象的建立在JVM中可能會進行重排序,在多線程訪問下存在風險,使用volatile修飾signleton實例變量有效,解決該問題。排序
/**
- Created by 張晨光 on 2020/6/12 11:22
- 雙重鎖模式
*/
public class Monitor {
private volatile static Monitor monitor;
private Monitor(){}
private static Monitor getInstance(){
if(monitor==null){
synchronized (Monitor.class){
if(monitor==null)
monitor=new Monitor();
}
}
return monitor;
}
}
4.1.4 靜態內部類
只有第一次調用getInstance方法時,虛擬機才加載 Inner 並初始化instance ,只有一個線程能夠得到對象的初始化鎖,其餘線程沒法進行初始化,保證對象的惟一性。目前此方式是全部單例模式中最推薦的模式,但具體仍是根據項目選擇。
/**
- Created by 張晨光 on 2020/6/12 11:29
- 靜態內部類
*/
public class JtSingleTon {
//private static JtSingleTon jtSingleTon;
private JtSingleTon(){}
private static JtSingleTon getInstance(){
return Inner.jtSingleTon;
}
private static class Inner{
private static final JtSingleTon jtSingleTon=new JtSingleTon();
}
}
4.1.5 枚舉實現
首先是再瞭解一下枚舉
/**
- Created by 張晨光 on 2020/6/12 15:36
- 枚舉測試;先來理解枚舉的原理;
*/
public enum EnumSingleTon {
INSTANCE; //關鍵字;
private EnumSingleTon(){
System.out.println("初始化...");
}
public static EnumSingleTon getInstance(){
return INSTANCE;
}
}
使用枚舉的這種,只初始化一次的特徵,來實現單例。
package single;
/**
- Created by 張晨光 on 2020/6/12 15:42
- User類,使用枚舉實現;
*/
public class User {
//1.私有的構造方法;
private User(){}
//2.利用枚舉類來獲取實例;在這裏放一個枚舉SingleTon
static enum SingleTon{
//有一個枚舉對象,天生爲單例;
INSTANCE;
private User user;
//私有的枚舉構造方法;只被初始化一次;
private SingleTon(){
user=new User();
}
//由枚舉提供一個獲取User類的實例方法
public User getInstance(){
return user;
}
}
//3.經過枚舉來獲取單例;
public static User getInstance(){
return SingleTon.INSTANCE.getInstance();
}
}
//調用測試方法,來測試User類是否單例的實現;br/>@Test
public void testEnumUser(){
User est1=User.getInstance();
User est2=User.getInstance();
System.out.println(est1);
System.out.println(est2);
}
總結:
1.理解:單例的概念
2.瞭解:懶漢式和餓漢式;建議會寫靜態內部類的實現;
用枚舉類來獲取實例;在這裏放一個枚舉SingleTon
static enum SingleTon{
//有一個枚舉對象,天生爲單例;
INSTANCE;
private User user;
//私有的枚舉構造方法;只被初始化一次;
private SingleTon(){
user=new User();
}
//由枚舉提供一個獲取User類的實例方法
public User getInstance(){
return user;
}
}
//3.經過枚舉來獲取單例;
public static User getInstance(){
return SingleTon.INSTANCE.getInstance();
}
}
//調用測試方法,來測試User類是否單例的實現;
@Test
public void testEnumUser(){
User est1=User.getInstance();
User est2=User.getInstance();
System.out.println(est1);
System.out.println(est2);
}
9
10
總結:
1.理解:單例的概念
2.瞭解:懶漢式和餓漢式;建議會寫靜態內部類的實現;
3.其餘的知道便可,根據本身的程度,看看就好了。
————————————————