激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java 實例解析單例模式

Java 實例解析單例模式

2022-03-08 00:37FranzLiszt1847 Java教程

單例模式(Singleton Pattern)是 Java 中最簡單的設計模式之一。這種類型的設計模式屬于創建型模式,它提供了一種創建對象的最佳方式,這種模式涉及到一個單一的類,該類負責創建自己的對象,同時確保只有單個對象被創建

單例模式的介紹

單例對象(Singleton)是一種常用的設計模式。在實際使用中,單例對象能保證在一個JVM中,該對象只存在一個實例存在。

優點

1、減少系統開銷,提高系統性能
2、省去了new操作符,降低了系統內存的使用頻率,減輕GC壓力
3、避免對共享資源的多重占用

缺點

1、不適應用多變的對象
2、擴展困難
3、單例類的職責過重,在一定程度上違背了“單一職責原則”。

Synchronized

Synchronized示例

介紹單例模式前,我們現介紹一下Synchronized
示例如下:
建立一個內部類,并開啟子線程,如果實例該類,則自動執行test1()方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class SynchronizedTest implements Runnable {
    private int count;
 
    public SynchronizedTest() {
        count = 0;
    }
 
    @Override
    public void run() {
        test1();
    }
 
    private void test1() {
        synchronized (this) {
            for (int i = 0; i < 5; i++) {
                try {
                    System.out.println(Thread.currentThread().getName() + ":" + count++);
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

構造一個SynchronizedTest 對象,傳入兩個線程對象

?
1
2
3
4
5
SynchronizedTest test = new SynchronizedTest();
       Thread thread1 = new Thread(test,"test1");
       Thread thread2 = new Thread(test,"test2");
       thread1.start();
       thread2.start();

由結果可知,當一個對象持有該代碼塊時,另一個線程訪問不到被鎖住的代碼塊,只要當前一線程執行完成,另一線程才能執行。

test1:0
test1:1
test1:2
test1:3
test1:4
test2:5
test2:6
test2:7
test2:8
test2:9

Synchronized與非Synchronized

建立一個內部類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class SynchronizedTest implements Runnable {
   private int count;
 
   public SynchronizedTest() {
       count = 0;
   }
 
   @Override
   public void run() {
       if (Thread.currentThread().getName().equals("S")) {
           test1();
       } else {
           test2();
       }
   }
 
   public void test1() {
       synchronized (this) {
           for (int i = 0; i < 5; i++) {
               try {
                   System.out.println(Thread.currentThread().getName() + ":" + (count++));
                   Thread.sleep(500);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }
       }
   }
 
   public void test2() {
       for (int i = 0; i < 5; i++) {
           try {
               System.out.println(Thread.currentThread().getName() + ":" + count);
               Thread.sleep(500);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
   }
}
?
1
2
3
4
5
SynchronizedTest test = new SynchronizedTest();
        Thread thread1 = new Thread(test,"S");
        Thread thread2 = new Thread(test,"N");
        thread1.start();
        thread2.start();

由結果可知,一個線程訪問Synchronized修飾的代碼塊,另一個線程訪問非Synchronized代碼塊不受阻塞

S:0
N:1
N:2
S:1
N:2
S:2
S:3
N:4
S:4
N:5

Singleton

第一個示例

此示例實現了單例,但是如果放在多線程當中,將會漏洞百出
我們接著看下一個改良示例

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Singleton {
/* 持有私有靜態實例,防止被引用,此處賦值為null,目的是實現延遲加載 */
private static Singleton instance = null;
    /* 私有構造方法,防止被實例化 */
    private Singleton() {
    }
    /* 靜態工程方法,創建實例 */
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

第二個示例

根據第一個示例,我們進行改良,加上Synchronized。
但是每次調用getInstance()方法時,都會對對象上鎖,為了減少系統開銷,我們一般在第一次創建對象的時候加鎖,后面就不需要了
我們接著看下一個改良示例

?
1
2
3
4
5
6
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}

第三個示例

我們對上一個示例進行改良,只有在instance == null的時候,也就是第一次創建對象的時候,執行加鎖的區域。此種寫法解決了上一個示例遺留的問題,但是在Java指令中創建對象和賦值操作是分開進行的,也就是說instance = new Singleton();語句是分兩步執行的。但是JVM并不保證這兩個操作的先后順序,也就是說有可能JVM會為新的Singleton實例分配空間,然后直接賦值給instance成員,然后再去初始化這個Singleton實例。

?
1
2
3
4
5
6
7
8
9
10
public static Singleton getInstance() {
if (instance == null) {
synchronized (instance) {
if (instance == null) {
instance = new Singleton();
      }
   }
 }
 return instance;
}

第四個示例

此代碼初看已經沒有問題,如果在構造方法中出現異常,那么實例將得不到創建

?
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Singleton {
/* 私有構造方法,防止被實例化 */
private Singleton() {
}
/* 此處使用一個內部類來維護單例 */
private static class SingletonFactory {
private static Singleton instance = new Singleton();
  }
/* 獲取實例 */
public static Singleton getInstance() {
return SingletonFactory.instance;
  }
}

第五個示例

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private static Singleton instance = null;
private Singleton(){
 
 }
 public static Singleton getInstance(){
     if (instance == null){
         sync();
     }
     return instance;
 }
private static synchronized void sync(){
     if (instance == null){
        instance = new Singleton();
         System.out.println("success");
    }
 }

到此這篇關于Java 實例解析單例模式的文章就介紹到這了,更多相關Java 單例模式內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://blog.csdn.net/News53231323/article/details/121034929

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美成人se01短视频在线看 | 一区二区视 | 狠狠干夜夜草 | 91久久国产露脸精品免费 | 精品久久久久久久久久久αⅴ | 精品一区二区久久久久久按摩 | 国产精品视频免费在线观看 | www国产网站| 欧美a级一区二区 | 91短视频在线观看视频 | 欧美精品成人 | 国产一区国产二区在线观看 | free korean xxxxhd| 亚洲国产二区 | 久久久综 | 欧美a欧美 | 国产小视频在线 | 黄色毛片一级视频 | 亚洲va久久久噜噜噜久牛牛影视 | 深夜福利视频绿巨人视频在线观看 | 九九热在线视频观看 | 久草在线新时代视觉 | 国产亚洲精品久久久久婷婷瑜伽 | 香蕉久久久久 | 亚洲国产精品一区二区久久 | 日韩毛片免费观看 | 亚洲精品久久久久久久久久 | 亚洲精品aⅴ中文字幕乱码 欧美囗交 | 久久亚洲精品国产一区 | 最近高清无吗免费看 | 鸳鸯谱在线观看高清 | 欧美日本91精品久久久久 | 成年人免费视频大全 | 欧美福利视频一区二区三区 | 曰本三级日本三级日本三级 | 黄色大片在线免费观看 | 俄罗斯16一20sex牲色另类 | 毛片在线免费播放 | 久久99精品国产自在现线 | 夜夜b| av人人|