How thread-safe is enum in java? I am implementing a Singleton using enum (as per Bloch's Effective Java), should I worry at all about thread safety for my singleton enum? Is there a way to prove or disprove that it is thread safe?
// Enum singleton - the preferred approach public enum Elvis { INSTANCE; public void leaveTheBuilding() { ... } }
Thanks
The enums are type-safe means that an enum has its own namespace, we can't assign any other value other than specified in enum constants. Typesafe enums are introduced in Java 1.5 Version. Additionally, an enum is a reference type, which means that it behaves more like a class or an interface.
Singleton With EnumSince enums are inherently serializable, we don't need to implement it with a serializable interface. The reflection problem is also not there. Therefore, it is 100% guaranteed that only one instance of the singleton is present within a JVM.
You can declare a function argument, return type, class member or local variable to be a particular Enum type and the compiler will enforce type safety; Enums are basically classes. They can implement interfaces, have behaviour and so on.
They are type safe and comparing them is faster than comparing Strings. Show activity on this post. If your set of parameters is limited and known at compile time, use enum . If your set of parameters is open and unkown at compile time, use strings.
As @Mike is saying, creation of enum is guaranteed to be thread safe. However, methods that you add to an enum class do not carry any thread safety guarantee. In particular, the method leaveTheBuilding
may be executed, concurrently, by multiple threads. If this method has side effects (changes the state of some variable) then you need to think about protecting it (i.e., make it synchronized
) or parts thereof.
Customized Enum Definition may be not thread safe. For example,
RoleEnum.java:
package com.threadsafe.bad; public enum RoleEnum { ADMIN(1), DEV(2), HEAD(3); private Integer value; private RoleEnum(Integer role){ this.value=role; } public static RoleEnum fromIntegerValue(Integer role){ for(RoleEnum x : values()){ if(x.value == role ){ return x; } } return RoleEnum.HEAD; } Class<?> buildFromClass; public void setBuildFromClass(Class<?> classType){ buildFromClass=classType; } public Class<?> getBuildFromClass(){ return this.buildFromClass; } }
Main.java:
package com.threadsafe.bad; public class Main { public static void main(String[] args) { // TODO Auto-generated method stub Thread threadA = new Thread(){ public void run(){ System.out.println("A started"); RoleEnum role; role=RoleEnum.fromIntegerValue(1); System.out.println("A called fromIntegerValue"); role.setBuildFromClass(String.class); System.out.println("A called setBuildFromClass and start to sleep"); try { Thread.sleep(10000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("Thread A: "+role.getBuildFromClass()); } }; Thread threadB = new Thread(){ public void run(){ System.out.println("B started"); RoleEnum role; role=RoleEnum.fromIntegerValue(1); role.setBuildFromClass(Integer.class); System.out.println("B called fromIntegerValue&setBuildFromClass and Start to sleep"); try { Thread.sleep(20000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("B waked up!"); System.out.println("Thread B: "+ role.getBuildFromClass()); } }; threadA.start(); threadB.start(); } }
Sometimes the output will be:
B started
B called fromIntegerValue&setBuildFromClass and Start to sleep
A started
A called fromIntegerValue
A called setBuildFromClass and start to sleep
Thread A: class java.lang.String
B waked up!
Thread B: class java.lang.String <-We expect java.lang.Integer
Sometimes the output will be:
A started
A called fromIntegerValue
A called setBuildFromClass and start to sleep
B started
B called fromIntegerValue&setBuildFromClass and Start to sleep
Thread A: class java.lang.Integer <-We expect java.lang.String
B waked up!
Thread B: class java.lang.Integer
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With