2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Das Singleton-Muster stellt sicher, dass eine Klasse nur eine Instanz hat, sich selbst instanziiert und diese Instanz dem gesamten System zur Verfügung stellt
Die Hauptfunktion des Singleton-Musters besteht darin, sicherzustellen, dass nur eine Instanz einer Klasse existiert
Zu verwendende Szenen:
● Als Seriennummerngenerator
● Webseitenzähler: Um zu vermeiden, dass der Datenbank bei jeder Aktualisierung Technologie hinzugefügt wird, speichern Sie sie zuerst im Cache
● Erstellen Sie Objekte, die zu viele Ressourcen verbrauchen, z. B. E/A- und Datenbankverbindungen usw.
Es gibt 7 Implementierungsmethoden für Singleton-Muster
Hauptsächlich unterteilt in den Hungry-Man-Stil und den Lazy-Man-Stil
Hungriger chinesischer Stil: Das Laden der Klasse führt dazu, dass das einzelne Instanzobjekt erstellt wird
Lazy-Stil: Das Laden von Klassen führt nicht dazu, dass ein Einzelinstanzobjekt erstellt wird, sondern wird erstellt, wenn das Objekt zum ersten Mal verwendet wird.
Hier ist eine Demonstration der besten Möglichkeit, das Singleton-Muster zu implementieren: Implementieren Sie das Singleton-Muster in Form einer Aufzählung und verwenden Sie es (Implementierung eines Seriennummerngenerators).
public enum SequenceGenerator {
INSTANCE;
private int sequenceNumber;
// 构造函数,初始化序列号为0
private SequenceGenerator() {
this.sequenceNumber = 0;
}
/**
* 获取下一个序列号。
* @return 下一个序列号
*/
public synchronized int getNextSequenceNumber() {
return sequenceNumber++;
}
}
// 测试类
public class SequenceGeneratorTest {
public static void main(String[] args) {
// 创建一个线程安全的列表来存储生成的序列号
List<Integer> sequenceNumbers = new CopyOnWriteArrayList<>();
// 创建多个线程来测试并发生成序列号
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < 1000; i++) {
executorService.submit(() -> {
int seq = SequenceGenerator.INSTANCE.getNextSequenceNumber();
sequenceNumbers.add(seq);
});
}
executorService.shutdown();
try {
executorService.awaitTermination(1, TimeUnit.MINUTES);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 输出所有生成的序列号,检查是否有重复
System.out.println(sequenceNumbers);
System.out.println("Total generated sequences: " + sequenceNumbers.size());
}
}
Die resultierende Ausgabe ist
In diesem Beispiel ist SequenceGenerator eine Aufzählungsklasse, die über ein privates sequenceNumber-Feld verfügt, das zum Speichern der aktuellen Sequenznummer verwendet wird. Die getNextSequenceNumber-Methode ist threadsicher, da sie als synchronisiert deklariert ist, wodurch sichergestellt wird, dass in einer Multithread-Umgebung keine Sequenznummernkonflikte auftreten.
In der SequenceGeneratorTest-Klasse verwenden wir einen ExecutorService, um eine gleichzeitige Umgebung zu simulieren, und verwenden eine threadsichere CopyOnWriteArrayList, um die generierten Sequenznummern zu sammeln, um die Richtigkeit der Sequenznummern zu überprüfen.
Bitte beachten Sie, dass das synchronisierte Schlüsselwort zwar die Thread-Sicherheit gewährleistet, in Szenarien mit hoher Parallelität jedoch die Leistung beeinträchtigen kann. Wenn der Sequenznummerngenerator mit sehr hoher Parallelität arbeiten muss, müssen Sie möglicherweise einen effizienteren Algorithmus in Betracht ziehen, z. B. die Verwendung atomarer Variablen (wie AtomicInteger) oder ein verteiltes Schema zur Generierung von Sequenznummern.