Skip to main content

Java Example

Non Thread Safe

  • Singleton
package refactoring_guru.singleton.example.non_thread_safe;

public final class Singleton {
private static Singleton instance;
public String value;

private Singleton(String value) {
// The following code emulates slow initialization.
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
this.value = value;
}

public static Singleton getInstance(String value) {
if (instance == null) {
instance = new Singleton(value);
}
return instance;
}
}
  • Multi Thread
package refactoring_guru.singleton.example.non_thread_safe;

public class DemoMultiThread {
public static void main(String[] args) {
System.out.println("If you see the same value, then singleton was reused (yay!)" + "\n" +
"If you see different values, then 2 singletons were created (booo!!)" + "\n\n" +
"RESULT:" + "\n");
Thread threadFoo = new Thread(new ThreadFoo());
Thread threadBar = new Thread(new ThreadBar());
threadFoo.start();
threadBar.start();
}

static class ThreadFoo implements Runnable {
@Override
public void run() {
Singleton singleton = Singleton.getInstance("FOO");
System.out.println(singleton.value);
}
}

static class ThreadBar implements Runnable {
@Override
public void run() {
Singleton singleton = Singleton.getInstance("BAR");
System.out.println(singleton.value);
}
}
}
If you see the same value, then singleton was reused (yay!)
If you see different values, then 2 singletons were created (booo!!)

RESULT:

FOO
BAR
  • Single Thread
package refactoring_guru.singleton.example.non_thread_safe;

public class DemoSingleThread {
public static void main(String[] args) {
System.out.println("If you see the same value, then singleton was reused (yay!)" + "\n" +
"If you see different values, then 2 singletons were created (booo!!)" + "\n\n" +
"RESULT:" + "\n");
Singleton singleton = Singleton.getInstance("FOO");
Singleton anotherSingleton = Singleton.getInstance("BAR");
System.out.println(singleton.value);
System.out.println(anotherSingleton.value);
}
}
If you see the same value, then singleton was reused (yay!)
If you see different values, then 2 singletons were created (booo!!)

RESULT:

FOO
FOO

Thread Safe

  • Singleton
package refactoring_guru.singleton.example.thread_safe;

public final class Singleton {
// The field must be declared volatile so that double check lock would work
// correctly.
private static volatile Singleton instance;

public String value;

private Singleton(String value) {
this.value = value;
}

public static Singleton getInstance(String value) {
// The approach taken here is called double-checked locking (DCL). It
// exists to prevent race condition between multiple threads that may
// attempt to get singleton instance at the same time, creating separate
// instances as a result.
//
// It may seem that having the `result` variable here is completely
// pointless. There is, however, a very important caveat when
// implementing double-checked locking in Java, which is solved by
// introducing this local variable.
//
// You can read more info DCL issues in Java here:
// https://refactoring.guru/java-dcl-issue
Singleton result = instance;
if (result != null) {
return result;
}
synchronized(Singleton.class) {
if (instance == null) {
instance = new Singleton(value);
}
return instance;
}
}
}
  • Multi Thread
package refactoring_guru.singleton.example.thread_safe;

public class DemoMultiThread {
public static void main(String[] args) {
System.out.println("If you see the same value, then singleton was reused (yay!)" + "\n" +
"If you see different values, then 2 singletons were created (booo!!)" + "\n\n" +
"RESULT:" + "\n");
Thread threadFoo = new Thread(new ThreadFoo());
Thread threadBar = new Thread(new ThreadBar());
threadFoo.start();
threadBar.start();
}

static class ThreadFoo implements Runnable {
@Override
public void run() {
Singleton singleton = Singleton.getInstance("FOO");
System.out.println(singleton.value);
}
}

static class ThreadBar implements Runnable {
@Override
public void run() {
Singleton singleton = Singleton.getInstance("BAR");
System.out.println(singleton.value);
}
}
}
If you see the same value, then singleton was reused (yay!)
If you see different values, then 2 singletons were created (booo!!)

RESULT:

BAR
BAR