| | |
| |
|
Единствен Јава објект (singleton) - Дополнување |
прегледано: |
200377 |
вкупно гласови: |
2 |
средна оценка: |
5.0 |
коментари: |
0 |
испрати до пријател
испечати
|
Singleton е една од најкористените Design Patterns и дефинитивно pattern кој што многу лесно се објаснува. Класичниот пример за Singleton беше претставен во претходниот напис:
public class MojSingleton {
private static MojSingleton instance = null;
private MojSingleton() {
...
...
}
public static MojSingleton getInstance () {
if (instance == null) {
instance = new MojSingleton();
}
return instance;
}
...
...
}
Овој пример е се што ви треба за 99% од вашите програми. Меѓутоа, овој пример може да биде проблематичен, посебно кога овој Singleton се користи во програма со повеќе нишки на извршување. Проблемот е во тоа што ако повеќе нишки го повикаат методот getInstance() во исто време, пред instance да биде иницијализиран, постои можност конструкторот MojSingleton() да биде повикан повеќе пати.
Повикувањето на MojSingleton() неколку пати, наместо само еднаш, се коси со нашата дефиниција на Sinleton. Во нашиот пример повикувањето на конструкторот MojSingleton() повеќе пати може и не е којзнае каков проблем, но замислете дека MojSingleton() во некој покомплициран пример отвара конекција до некоја база на податоци. Доколку MojSingleton() се повика повеќе од еднаш тогаш ние имаме повеќе од една конекција кон базата на податоци, иако целта ни беше да имаме една и само една конекција кон таа база на податоци.
Зошто всушност овој пример не е thread-safe?
Сценарио 1:
1. Програмот се стартува. MojSingleton.getInstance() сеуште не е повикан.
2. Нишка 1 го повикува методот getInstance().
3. Нишка 1 проверува дали (instance == null)
4. Нишка 1 утврдува дека instance е null и преминува на наредната линија
(instance = new MojSingleton();)
5. Нишка 1 завршува со своите циклуси и контролата се префрла на Нишка 2,
пред (instance = new MojSingleton();) да биде извршено.
6. Нишка 2 го повикува методот getInstance()
7. Нишка 2 утврдува дека instance е сеуште null и преминува на наредната
линија.
8. Нишка 2 повикува: instance = new MojSingleton();
9. Нишка 2 завршува со методот и ја враќа креираната инстанца од
MojSingleton().
10. Нишка 1 се буди и продолжува со извршување таму каде што беше запрена.
11. Нишка 1 повикува: instance = new MojSingleton();
12. Нова инстанца од MojSingleton() е креирана иако целта ни беше да креираме
само една. ПРОБЛЕМ !!!
Првото и наједноставно решение за овој проблем е да ги искористиме механизмите кои што се вградени во самата Јава Виртуелна Машина. Претходниот напис за Singleton го искористи клучниот збор synchronized за да го реши овој проблем. Кога некој метод ќе се дефинира како synchronized, самата виртуелна машина ќе се погрижи дека само една нишка може да го извршува методот getInstance() во било кое време.
Тоа значи дека после чекорот 5 во претходното сценарио, нишка 2 нема да може да го повика методот getInstance() се додека нишка 1 не заврши со извршувањето на методот. Кога нишка 2 конечно ќе почне да го извршува методот getInstance(), instance е веќе инстанцирана и нишка 2 нема да креира нова инстанца. Со тоа сме го решиле проблемот со thread-safe Singleton како во примерот подолу:
public class MojSingleton{
private static MojSingleton instance = null;
private MojSingleton() {
...
...
}
public static synchronized MojSingleton getInstance () {
if (instance == null) {
instance = new MojSingleton();
}
return instance;
}
...
...
}
Но, придобивките од користење на клучниот збор synchronized се и негова најголема маана. Да се потсетиме: “Кога еден метод е маркиран како synchronized, една и само една нишка може да го извршува било кое дадено време”. Тоа значи дека доколку 100 нишки го повикаат методот getInstance() во еден исти момент, самое една нишка ќе може да го извршува. Сите други нишки ќе бидат блокирани и ќе мораат да чекаат. Значи, иако synchronized ги решава проблемите со threadsafety, користење на зборот synzhronized дефинитивно ќе ги забави вашите програми. Посебно во програми во кои getInstance() се повикува премногу често. Доколку вашите програми не се погодени од користењето на клучниот збор synchronized пред методот getInstance() тогаш може да го користите примерот прикажан погоре. Но кога и да е ќе се најдете во ситуација кога вашиот синxронизиран Singleton ќе ви направи проблем. За во тие ситуации би посакале да го имате прочитано делот кој што следува и се однесува на други примери на thread-safe Singleton кои што не користат синхронизиран getInstance() метод.
Доколку обратите внимание на примерот на Singleton, лесно ќе заклучите дека getInstance() методот треба да биде синхронизиран само првиот пат кога се повикува.
|
|
|
|
|
|
| |
|
|
---|
JavaTM и Java-базираните ознаки се трговски марки или регистрирани трговски марки на Sun Microsystems, Inc. во САД и други држави. Java.com.mk никако не соработува со Sun Microsystems, Inc. Сите други трговски марки се сопственост на нивните сопственици. |
|