.餓漢式單例類
站在用戶的角度思考問題,與客戶深入溝通,找到鹽都網站設計與鹽都網站推廣的解決方案,憑借多年的經驗,讓設計與互聯(lián)網技術結合,創(chuàng)造個性化、用戶體驗好的作品,建站類型包括:成都網站設計、網站建設、外貿網站建設、企業(yè)官網、英文網站、手機端網站、網站推廣、域名注冊、雅安服務器托管、企業(yè)郵箱。業(yè)務覆蓋鹽都地區(qū)。
//餓漢式單例類.在類初始化時,已經自行實例化
public class Singleton1 {
//私有的默認構造子
private Singleton1() {}
//已經自行實例化
private static final Singleton1 single = new Singleton1();
//靜態(tài)工廠方法
public static Singleton1 getInstance() {
return single;
}
}
2.懶漢式單例類
//懶漢式單例類.在第一次調用的時候實例化
public class Singleton2 {
//私有的默認構造子
private Singleton2() {}
//注意,這里沒有final
private static Singleton2 single=null;
//靜態(tài)工廠方法
public synchronized static Singleton2 getInstance() {
if (single == null) {
single = new Singleton2();
}
return single;
}
}
//對懶漢式單例的改進(錯誤的改進)
//實際上,只有在第一次創(chuàng)建對象的時候需要加鎖,之后就不需要了 ,這樣可以提升性能
public synchronized static Singleton2 getInstance() {
if (instance == null) {
synchronized(instance){ //鎖住當前實例對象
if(instance == null){
instance = new Singleton2();
}
}
}
return instance;
}
錯誤原因:
aA、B線程同時進入了第一個if判斷
bA首先進入synchronized塊,由于instance為null,所以它執(zhí)行instance = new Singleton();
c由于JVM內部的優(yōu)化機制,JVM先畫出了一些分配給Singleton實例的空白內存,并賦值給instance成員(注意此時JVM沒有開始初始化這個實例),然后A離開了synchronized塊。
dB進入synchronized塊,由于instance此時不是null,因此它馬上離開了synchronized塊并將結果返回給調用該方法的程序。
e此時B線程打算使用Singleton實例,卻發(fā)現(xiàn)它沒有被初始化,于是錯誤發(fā)生了。
正確改進(使用內部類):
JVM內部的機制能夠保證當一個類被加載的時候,這個類的加載過程是線程互斥的,JVM能夠幫我們保證instance只被創(chuàng)建一次,
并且會保證把賦值給instance的內存初始化完畢,這樣我們就不用擔心上面的問題。
同時該方法也只會在第一次調用的時候使用互斥機制,這樣就解決了低性能問題
public?class?Singleton?{??
??
/*?私有構造方法,防止被實例化?*/??
private?Singleton(){
}
/*?此處使用一個內部類來維護單例?*/??
private?static?class?SingletonFactory?{??
private?static?Singleton?instance?=?new?Singleton();??
}
/*?獲取實例?*/??
public?static?Singleton?getInstance()?{??
return?SingletonFactory.instance;??
}
/*?如果該對象被用于序列化,可以保證對象在序列化前后保持一致?*/??
public?Object?readResolve()?{??
return?getInstance();??
}
}
其實說它完美,也不一定,如果在構造函數(shù)中拋出異常,實例將永遠得不到創(chuàng)建,也會出錯????
第二種改進:
因為我們只需要在創(chuàng)建類的時候進行同步,所以只要將創(chuàng)建和getInstance()分開,
單獨為創(chuàng)建加synchronized關鍵字,也是可以的
public class Singleton {
private static Singleton instance=null;
private Singleton(){}
private static synchronized void Init(){
if(instance==null)
instance=new Singletion();
}
public static Singleton getInstance(){
if(instance==null){
Init();
}
return instance;
}
}
3.登記式單例類
import java.util.HashMap;
import java.util.Map;
//登記式單例類.
//類似Spring里面的方法,將類名注冊,下次從里面直接獲取。
public class Singleton3 {
private static MapString,Singleton3 map = new HashMapString,Singleton3();
static{
Singleton3 single = new Singleton3();
map.put(single.getClass().getName(), single);
}
//保護的默認構造子
protected Singleton3(){}
//靜態(tài)工廠方法,返還此類惟一的實例
public static Singleton3 getInstance(String name) {
if(name == null) {
name = Singleton3.class.getName();
System.out.println("name == null"+"---name="+name);
}
if(map.get(name) == null) {
try {
map.put(name, (Singleton3) Class.forName(name).newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return map.get(name);
}
//一個示意性的商業(yè)方法
public String about() {
return "Hello, I am RegSingleton.";
}
public static void main(String[] args) {
Singleton3 single3 = Singleton3.getInstance(null);
System.out.println(single3.about());
}
}
第一個
public interface RandomNumberListener {//接口
public void numberChanged(double d);
}
第二個
public class Consol implements RandomNumberListener{
@Override
public void numberChanged(double d) {
System.out.println(d);
}
}
第三個
public class SwingWindow
extends JFrame
implements RandomNumberListener{//觀察者
private JLabel label = new JLabel();
public SwingWindow(){
this.getContentPane().add( label);
this.setSize(300,200);
this.setVisible(true);
}
@Override
public void numberChanged(double d) {
label.setText(String.valueOf(d));
}
}
第四個
public class RandomNumber {//業(yè)務
private double r;
private ListRandomNumberListener listeners = new ArrayListRandomNumberListener();
//添加所有觀察者
public void addRandomNumberListener(RandomNumberListener lis){
listeners.add(lis);
}
public void random(){
r = Math.random();
//數(shù)據(jù)發(fā)生改變,通知所有的觀察者
for (RandomNumberListener lis : listeners) {
lis.numberChanged(r);
}
}
}
第五個
public class Test {
public static void main(String[] args) throws InterruptedException{
RandomNumber rn = new RandomNumber();
SwingWindow sw = new SwingWindow();
Consol c = new Consol();
rn.addRandomNumberListener(sw);
rn.addRandomNumberListener(c);
while(true){
rn.random();
Thread.sleep(new Random().nextInt(3000)+1000L);
}
}
}
嗯,是策略模式,代碼如下。你把里面你要的獎金計算好就可以用了。建議樓主去看下《大話設計模式》或者《java設計模式》里面講的挺生動的。
//獎金接口
public interface Bonus {
Double calcBonus();
}
//累計獎金
public class AccumulativeBouns implements Bonus{
public Double calcBonus() {
//總的匯款額*0.1%
return 0.0;
}
}
//業(yè)務獎金
public class BusinessBonus implements Bonus{
public Double calcBonus(){
//每個人當月業(yè)務獎金=當月銷售額*3%
return 0.0;
}
}
//團隊獎金
public class TeamBonus implements Bonus{
public Double calcBonus(){
//團隊總銷售額*1%
return 0.0;
}
}
public class BounsContext {
private Bonus bonus;
public BounsContext(Bonus bonus){
this.bonus=bonus;
}
public double calcBonus(){
return bonus.calcBonus();
}
}
調用..
public class MainTest {
public static void main(String [] args){
//累計獎金
BounsContext bounsContext=null;
bounsContext =new BounsContext(new AccumulativeBouns());
bounsContext.calcBonus();
//團隊獎金
bounsContext=new BounsContext(new TeamBonus());
bounsContext.calcBonus();
//業(yè)務獎金
bounsContext=new BounsContext(new BusinessBonus());
bounsContext.calcBonus();
}
}