Friday, January 04, 2008

Singleton ?

ใครใช้ Java ก็คงรู้สึกว่า Singleton เป็นส่วนหนึ่งของชีวิต (โดยเฉพาะ Lazy-loaded)
เมื่อก่อน (นานมาแล้ว)
เขานิยมใช้ pattern แบบนี้
class MyClass {
private static MyClass instance;

private MyClass() {}

public static MyClass getInstance() {
if (instance == null) {
instance = new MyClass();
}
return instance;
}
}

ซึ่งก็ใช้ได้ ยกเว้นว่า ถ้าอยู่ในสภาพแวดล้อมแบบ concurrency แล้ว ก็มีโอกาสที่ MyClass จะถูกสร้างซ้ำซ้อนได้มากกว่า 1 ครั้ง
สมัยนั้นมีคนถกเถียงเรื่องนี้อยู่วุ่นวาย แต่ผมขี้เกียจอ่านและติดตาม
(ใครสนใจว่าถกกันอย่างไร ลองอ่านตัวอย่างอันนี้ดู The double-checked locking is broken)
ถึงจะรู้ว่ามีปัญหาเรื่อง concurrency แต่ผมก็ใช้ pattern นี้มาตลอด (โดยแอบเข้าข้างตัวเองว่า เอาน่า อย่างมากก็เปลือง resource นิดๆหน่อยๆ)
จนมาภายหลังที่มี springframework ออกมา ผมก็เลยยกหน้าที่นี้ให้ spring ไป

จนมาเมื่อวาน อ่านหนังสือเล่มหนึ่ง พบว่าเขามีวิธีการเขียนแบบใหม่ที่ดีกว่ากว่าแล้ว
เรียกว่า Initialization on demand holder idiom
public class Something
{
private Something() {}

private static class LazyHolder
{
private static final Something something = new Something();
}

public static Something getInstance()
{
return LazyHolder.something;
}
}


เป็นอันว่าเรื่องนี้ผมตกข่าวไป เพราะใน history ของ wiki เห็นเขาเขียนเรื่องนี้มาตั้งแต่ July 2006 แล้ว

Related link from Roti

5 comments:

Prach Pongpanich said...

สวัสดีปีใหม่ครับพี่ , ไปเที่ยวไหนมาบ้างครับ

Anonymous said...

ขอบคุณครับ ได้ความรู้ใหม่
ผมก็คิดหมือนกันครับว่า
อย่างมากก็เปลือง resource นิดหน่อยจริงๆด้วย 555

hus said...

อืม ผมมาคิดว่ามันอาจจะมีปัญหามากกว่า resource
หรือปล่าวครับ เช่น value ที่อยู่ใน myClass หน่ะครับ
มันจะไม่ถูกต้องหรือปล่าวครับ ถ้ามาจากคนละ instance

PPhetra said...

hus: จะมีปัญหา concurrency หรือไม่ ขึ้นอยู่กับ design นะ

hus said...

pphetra: จริงด้วย ขอบคุณครับ ถ้าไม่เก็บ state ไว้ใน singleton ก็คงไม่มีปัญหาเรื่อง concurrency