Como se ha mencionado, hasta cierto punto, una enumeración es una clase de Java con la condición especial de que su definición debe comenzar con al menos una "constante de enumeración".
Aparte de eso, y que las enumeraciones no pueden extenderse o usarse para extender otras clases, una enumeración es una clase como cualquier clase y la usa agregando métodos debajo de las definiciones constantes:
public enum MySingleton {
INSTANCE;
public void doSomething() { ... }
public synchronized String getSomething() { return something; }
private String something;
}
Accede a los métodos de singleton a lo largo de estas líneas:
MySingleton.INSTANCE.doSomething();
String something = MySingleton.INSTANCE.getSomething();
El uso de una enumeración, en lugar de una clase, es, como se ha mencionado en otras respuestas, principalmente sobre una instanciación segura de subprocesos del singleton y una garantía de que siempre será solo una copia.
Y, quizás, lo más importante, que este comportamiento está garantizado por la propia JVM y la especificación Java.
Aquí hay una sección de la especificación de Java sobre cómo se evitan varias instancias de una instancia de enum:
Un tipo de enumeración no tiene instancias distintas de las definidas por sus constantes de enumeración. Es un error en tiempo de compilación intentar crear una instancia explícita de un tipo de enumeración. El método de clonación final en Enum asegura que las constantes enum nunca se puedan clonar, y el tratamiento especial por el mecanismo de serialización asegura que nunca se creen instancias duplicadas como resultado de la deserialización. Se prohíbe la creación de instancias reflexivas de tipos de enumeración. Juntas, estas cuatro cosas aseguran que no existan instancias de un tipo enum más allá de las definidas por las constantes enum.
Vale la pena señalar que después de la instanciación, cualquier problema de seguridad de subprocesos debe manejarse como en cualquier otra clase con la palabra clave sincronizada, etc.