- イントロダクション
- 【1】静的初期化(Eager Initialization)
- 【2】synchronized メソッドで遅延初期化
- 【3】ダブルチェックロッキング(Double-Checked Locking)
- 【4】内部クラス(Initialization-on-demand holder idiom)
- 【5】Enum を使うシングルトン(最強)
- ◆ SingletonEager.java
- ◆ SingletonSync.java
- ◆ SingletonDCL.java
- ◆ SingletonHolder.java
- ◆ SingletonEnum.java
- 📘 自己学習したい人へ
- 🎓 プログラムのレビューを受けたい人、転職したい人へ
イントロダクション
Java で開発していると、「このクラスはアプリ全体で一つだけのインスタンスを持たせたい」という場面が必ず出てきます。
例えば:
- ログを記録するクラス
- 設定を管理するクラス
- データベース接続を管理するクラス
- キャッシュを保持するクラス
こうした「ひとつでいいもの」を複数作られてしまうと、処理の不整合や不具合につながります。そこで使われるのが シングルトンパターン(Singleton Pattern) です。
ただし、ここで一つ注意があります。
❗問題:普通のシングルトン実装はマルチスレッドに弱い
初心者がよく書く「普通のシングルトン」は、複数スレッドから同時にアクセスされると、複数インスタンスが生成される危険性があります。
そこで必要なのが スレッドセーフなシングルトン。
本記事では、Java で実現できる代表的な 5つのスレッドセーフなシングルトン実装を、
コード+解説付きでわかりやすくまとめます。
さらに Java でシングルトンを扱う際に役立つ考え方、選び方の基準まで丁寧に説明します。
最後には、あなたの学習をさらに加速させる 学習書籍とスクールの案内 も掲載しているので、ぜひ最後まで読んでください。
目次
【一】シングルトンパターンとは?
【二】スレッドセーフとは?
【三】スレッドセーフなシングルトン5種類まとめ
1:静的初期化(Eager Initialization)
2:メソッドを synchronized にする方法
3:ダブルチェックロッキング(DCL)
4:内部クラス(Holder パターン)
5:Enum を使った超安全シングルトン
【四】5つのコードをまとめたサンプル Java プロジェクト
【五】どの方法を選べばいいの?
【六】Java の強みとシングルトンの相性
【七】学習の次のステップ:おすすめ教材とスクール
【八】まとめ
【一】シングルトンパターンとは?
シングルトンパターンとは、
クラスのインスタンスをアプリケーション内でただ一つだけにする構造
のことです。
メリットは以下のとおり:
- 無駄なインスタンス生成を避けられる
- グローバルのようにどこからでもアクセス可能
- 状態を一元管理できる
ただし、ただ一つだけ作るためには慎重な実装が必要です。
特にマルチスレッドの場合、気を抜くとインスタンスが複数作られる危険があります。
【二】スレッドセーフとは?
スレッドセーフとは、
複数のスレッドが同時に実行されても、値の矛盾や内部状態の破壊が起きない状態
のことです。
もし getInstance() を同時に呼ばれたらどうなるでしょう?
インスタンスが 2つ、3つ… と生成されることがあります。
だからこそ、正しい実装が必須なのです。
【三】スレッドセーフなシングルトン5種類まとめ
ここから、スレッドセーフな5つの実装方法を順番に紹介していきます。
【1】静的初期化(Eager Initialization)
最初からインスタンスを作っておく方法です。
|
1 2 3 4 5 6 7 8 9 10 |
public class SingletonEager { private static final SingletonEager INSTANCE = new SingletonEager(); private SingletonEager() { } public static SingletonEager getInstance() { return INSTANCE; } } |
特徴
- クラスが読み込まれるタイミングで 1 インスタンス作成
- スレッドセーフ
- パフォーマンスが良い
デメリット
- 使わなくても作られる
- 重い初期化には向かない
【2】synchronized メソッドで遅延初期化
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public class SingletonSync { private static SingletonSync instance; private SingletonSync() { } public static synchronized SingletonSync getInstance() { if (instance == null) { instance = new SingletonSync(); } return instance; } } |
特徴
- 遅延初期化ができる
- synchronized によりスレッドセーフ
デメリット
- パフォーマンスが低下しやすい
- 毎回ロックが発生する
【3】ダブルチェックロッキング(Double-Checked Locking)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public class SingletonDCL { private static volatile SingletonDCL instance; private SingletonDCL() { } public static SingletonDCL getInstance() { if (instance == null) { synchronized (SingletonDCL.class) { if (instance == null) { instance = new SingletonDCL(); } } } return instance; } } |
特徴
- 初回のみ同期をとり、その後はロックしない
- 再チェックで安全性を確保
- volatile が重要
メリット
- 高速
- 遅延初期化可能
- 業務でよく使われる
デメリット
- 実装が複雑でミスしやすい
【4】内部クラス(Initialization-on-demand holder idiom)
|
1 2 3 4 5 6 7 8 9 10 11 12 |
public class SingletonHolder { private SingletonHolder() { } private static class Holder { private static final SingletonHolder INSTANCE = new SingletonHolder(); } public static SingletonHolder getInstance() { return Holder.INSTANCE; } } |
特徴
- Java のクラスロードの仕組みを利用
- 遅延初期化+スレッドセーフ+高速
- コードが綺麗
メリット
- 初心者にも書きやすい
- 実務でもかなり使われる
【5】Enum を使うシングルトン(最強)
|
1 2 3 4 5 6 7 8 |
public enum SingletonEnum { INSTANCE; public void doSomething() { // 処理 } } |
特徴
- Java の仕様により完全スレッドセーフ
- シリアライズも安全
- 反射攻撃も防げる
メリット
- 最も安全
- コードが圧倒的に短い
- ほぼ欠点なし
【四】5つのシングルトン実装をまとめたサンプルプロジェクト
以下は「5つのパターンをすべてまとめた Java サンプルコード集」です。
あなたの IDE にコピペすればそのまま実行できます。
◆ SingletonEager.java
|
1 2 3 4 5 6 7 8 9 10 |
public class SingletonEager { private static final SingletonEager INSTANCE = new SingletonEager(); private SingletonEager() { } public static SingletonEager getInstance() { return INSTANCE; } } |
◆ SingletonSync.java
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public class SingletonSync { private static SingletonSync instance; private SingletonSync() { } public static synchronized SingletonSync getInstance() { if (instance == null) { instance = new SingletonSync(); } return instance; } } |
◆ SingletonDCL.java
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public class SingletonDCL { private static volatile SingletonDCL instance; private SingletonDCL() { } public static SingletonDCL getInstance() { if (instance == null) { synchronized (SingletonDCL.class) { if (instance == null) { instance = new SingletonDCL(); } } } return instance; } } |
◆ SingletonHolder.java
|
1 2 3 4 5 6 7 8 9 10 11 12 |
public class SingletonHolder { private SingletonHolder() { } private static class Holder { private static final SingletonHolder INSTANCE = new SingletonHolder(); } public static SingletonHolder getInstance() { return Holder.INSTANCE; } } |
◆ SingletonEnum.java
|
1 2 3 4 5 6 7 8 |
public enum SingletonEnum { INSTANCE; public void doSomething() { System.out.println("Enum Singleton Working!"); } } |
【五】どの方法を選べばいいの?
目的別に選ぶと失敗しません。
- 安全性・拡張性・簡易さを優先 → Enum
- 遅延初期化 + 安全性 + 高速 → Holder パターン
- 細かく制御したい → DCL
- 初学者で手を動かしながら覚えたい → synchronized
- 起動時に必ず使う → 静的初期化
【六】Java の強みとシングルトンの相性
Java は
- マルチスレッドが標準レベルで強い
- JVM がクラスロードの安全性を保証する
- volatile、同期化などの仕組みが充実
といった特徴から、シングルトンのような「インスタンス管理パターン」と非常に相性が良い言語です。
特に 内部クラス(Holder パターン) は Java の仕組みを最大限活かした方法であり、Java を深く学ぶほど「美しい」と感じられるでしょう。
【七】学習の次のステップ
ここからさらに Java を深めたい人に、2つの選択肢をおすすめします。
📘 自己学習したい人へ
まずは文章で体系的に学びたい方へ、
👉 「絶対にJavaプログラマーになりたい人へ。」
https://amzn.asia/d/3E1CYbv
Java を最短で実務レベルに近づける内容なので、独学の土台を固めるのに最適です。
🎓 プログラムのレビューを受けたい人、転職したい人へ
自己学習でつまずいた人、コードレビューがほしい人、転職サポートも受けたい人は、
👉 サイゼントアカデミー
https://academy.cyzennt.co.jp
Java 専門で、完全初心者からでもプログラマー転職を目指せるスクールです。
「コードの書き方が分からない…」「エラーが直らない…」という時の手厚いサポートが強みです。
【八】まとめ
この記事では、Java で可能な スレッドセーフなシングルトン5種類をすべて解説しました。
- 静的初期化
- synchronized
- ダブルチェックロッキング
- 内部クラス(Holder)
- Enum(最強)
どれも正しく使えば Java の強力な味方になります。
シングルトンは Java 学習において必ず通る道なので、ぜひこの記事のコードを手元で動かしながら理解を深めてください。

コメント