[Java] Design Pattern, Singleton per thread

Pagina: 1
Acties:
  • 119 views sinds 30-01-2008
  • Reageer

  • maartenvdv737
  • Registratie: Augustus 2000
  • Laatst online: 05:49
Ik heb een Singleton class met een static get methode die een instance van het object terug geeft.
Op deze manier kan ik het object globaal gebruiken.

Op zich werkt dit prima, maar nu heb ik parallel in threads meerdere instanties van dit object nodig. Wat ik dus wil is per thread die singleton globaal hebben, maar niet tussen threads.

Ik kan niet ergens vinden hoe dit moet en of dit kan. Kan iemand me in de juiste richting sturen?

Hieronder nog de class:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class FedQueryEngineFactory implements QueryEngineFactory {
  
    static boolean registered = false; 
    
    private Configuration config;
    private static FedQueryEngineFactory instance = null;
    
    public static void register(Configuration conf) {
        // register only once
        if (!registered) { 
            instance = new FedQueryEngineFactory(conf);
            QueryEngineRegistry.addFactory(instance);
            registered=true;
        }
    }
    
    public static void unregister() {
        QueryEngineRegistry.removeFactory(instance);
        registered=false;
    }
    
    
    /**
     * @return Returns the instance.
     */
    public static FedQueryEngineFactory getInstance() {
        return instance;
    }

}

Ik blijf er iig vrij nuchter onder....


  • -FoX-
  • Registratie: Januari 2002
  • Niet online

-FoX-

Carpe Diem!

Waarom wil je perse een singleton per thread hebben? Als dit is om multithreaded te kunnen werken, kan je beter je code aanpassen zodat deze thread-safe is. Wat je ook kan doen is de bestuurder van de thread, volatile instance variabele geven.. op die manier worden de instance variabele per thread gekopieerd en komen ze niet in mekaars vaarwater

  • Robtimus
  • Registratie: November 2002
  • Laatst online: 01-12 19:51

Robtimus

me Robtimus no like you

Niet helemaal netjes, maar volgens mij werkt het wel, hou een (synchronized) map bij, waarbij de key een thread is en de value je instance per thread. Vervolgens haal je met Thread.currentThread je huidige thread op, die je gebruikt in de get method van je map.

More than meets the eye
There is no I in TEAM... but there is ME
system specs


  • Kwistnix
  • Registratie: Juni 2001
  • Laatst online: 08:22
Je kan jouw Singleton wellicht combineren met java.lang.ThreadLocal.

Edit:

Zie "Java Concurrency In Practice" (ISBN: 0-321-34960-1)

[ Voor 94% gewijzigd door Kwistnix op 31-01-2007 23:34 ]


Verwijderd

-FoX- schreef op woensdag 31 januari 2007 @ 22:13:
Wat je ook kan doen is de bestuurder van de thread, volatile instance variabele geven.. op die manier worden de instance variabele per thread gekopieerd en komen ze niet in mekaars vaarwater
Euh volatile zorgt niet op een magische manier voor meerdere instanties hoor, of begrijp ik gewoon helemaal niet wat je bedoeld?

Ik zou overigens bij het aanmaken van een nieuwe thread simpelweg een nieuwe instanties van dat object aanmaken. Want in essentie komt het waar nu toch al op neer. Dan hoef je dus helemaal niets te syncen zo lang je het maar in de thread houdt.

  • Stephan Oudmaijer
  • Registratie: Oktober 2000
  • Laatst online: 16-08-2023
Je zult ook moeten letten op synchronisatie, en zoals hierboven al werd gezegd, kijk eens naar ThreadLocal.

  • -FoX-
  • Registratie: Januari 2002
  • Niet online

-FoX-

Carpe Diem!

Verwijderd schreef op donderdag 01 februari 2007 @ 07:15:
[...]
Euh volatile zorgt niet op een magische manier voor meerdere instanties hoor, of begrijp ik gewoon helemaal niet wat je bedoeld?
Nee, volatile zorgt niet voor meerdere instanties.. maar zorgt er wel voor dat het als member niet gedeeld wordt met andere threads

  • Tubby
  • Registratie: Juni 2001
  • Laatst online: 01-12 20:10

Tubby

or not to be

wat je wil is ThreadLocal :)

tubby.nl - Artes Moriendi - q1 - bf1942 - WoT - pubg - LinkedIN


  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 01-12 20:19

Gerco

Professional Newbie

@-FoX-:
vziw zorgt volatile er juist voor dat een member variable altijd in sync is tussen meerdere threads. Het is juist voor het delen van 1 variabele tussen threads.
A field may be declared volatile, in which case a thread must reconcile its working copy of the field with the master copy every time it accesses the variable. Moreover, operations on the master copies of one or more volatile variables on behalf of a thread are performed by the main memory in exactly the order that the thread requested.

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


  • -FoX-
  • Registratie: Januari 2002
  • Niet online

-FoX-

Carpe Diem!

Gerco schreef op donderdag 01 februari 2007 @ 08:14:
@-FoX-:
vziw zorgt volatile er juist voor dat een member variable altijd in sync is tussen meerdere threads. Het is juist voor het delen van 1 variabele tussen threads.
Er is uiteraard maar 1 algemene member variabele. Maar ik heb me misschien wel verkeerd uitgedrukt. Van een volatile gemarkeerde member zal een lokale kopie genomen worden door de thread die deze accessed, om ervoor te zorgen dat de interne state van deze member niet gecorrumpeerd wordt, worden de bewerkingen op deze lokale kopie gedaan (en achteraf weer gesynced). Het is dus een manier om je member thread-safe te krijgen. En misschien is dat het enige dat de TS voor ogen heeft?

  • maartenvdv737
  • Registratie: Augustus 2000
  • Laatst online: 05:49
Verwijderd schreef op donderdag 01 februari 2007 @ 07:15:
[...]
Ik zou overigens bij het aanmaken van een nieuwe thread simpelweg een nieuwe instanties van dat object aanmaken. Want in essentie komt het waar nu toch al op neer. Dan hoef je dus helemaal niets te syncen zo lang je het maar in de thread houdt.
Ik ben niet zo thuis in de design patterns, maar aangezien ik hier met een third party library werk waarin ik met een hook wat dingen kan doen, heb ik dit inderdaad geprobeerd. In de thread een nieuwe instantie maken van de factory. Dit lijkt echter niet te helpen.

Ik zal eens kijken naar ThreadLocal

Ik blijf er iig vrij nuchter onder....


  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 01-12 20:19

Gerco

Professional Newbie

-FoX- schreef op donderdag 01 februari 2007 @ 08:55:
Van een volatile gemarkeerde member zal een lokale kopie genomen worden door de thread die deze accessed, om ervoor te zorgen dat de interne state van deze member niet gecorrumpeerd wordt, worden de bewerkingen op deze lokale kopie gedaan (en achteraf weer gesynced).
Ik begrijp (geloof ik) wat je bedoelt, maar zo werkt het imo niet. Het heeft wel hetzelfde effect, er komt een lock op je volatile variabele zodat maar 1 thread deze tegelijkertijd kan bewerken. Prima voor primitive types, maar wat als je nu een Object hebt in je volatile?

Stel Thread 1 roept method1() aan op dat Object (Eerst synced de JVM dan de reference naar dat object met main memory). Dan roept Thread 2 method2() aan op dat object (met weer een synchronizatie). Dan is het best mogelijk dat method1() en method2() elkaar in de weg zitten. Er zit namelijk geen lock op dat object zelf, maar alleen op de variabele die ernaar wijst. Je zult in die situatie nog steeds het object zelf thread-safe moeten maken.

[ Voor 4% gewijzigd door Gerco op 01-02-2007 09:14 ]

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


  • Kwistnix
  • Registratie: Juni 2001
  • Laatst online: 08:22
-FoX- schreef op donderdag 01 februari 2007 @ 08:55:
[...]

Er is uiteraard maar 1 algemene member variabele. Maar ik heb me misschien wel verkeerd uitgedrukt. Van een volatile gemarkeerde member zal een lokale kopie genomen worden door de thread die deze accessed, om ervoor te zorgen dat de interne state van deze member niet gecorrumpeerd wordt, worden de bewerkingen op deze lokale kopie gedaan (en achteraf weer gesynced). Het is dus een manier om je member thread-safe te krijgen. En misschien is dat het enige dat de TS voor ogen heeft?
Volatile variabelen worden niet in registers gecached en zijn niet per definitie een thread safety garantie, want ze kunnen alleen het visibility aspect garanderen. Volgens het boek dat ik al eerder aanhaalde kan je volatile alleen toepassen als je aan de volgende eisen voldoet:
  • Writes to the variable do not depend on its current value, or you can ensure that only a single thread ever updates the value.
  • The variable does not participate in invariants with other state variables.
  • Locking is not required for any other reason while the variable is being accessed.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

FallenAngel666 schreef op donderdag 01 februari 2007 @ 09:36:
[...]


Volatile variabelen worden niet in registers gecached en zijn niet per definitie een thread safety garantie, want ze kunnen alleen het visibility aspect garanderen. Volgens het boek dat ik al eerder aanhaalde kan je volatile alleen toepassen als je aan de volgende eisen voldoet:


[...]
+1

Verder kunnen ze ook reorderings voorkomen + ze kunnen gebruikt worden voor save handoffs (piggybacking on synchronization): een techniek waarmee data met visibility problemen toch threadsafe gebruikt kan worden.

Verder zou ik oppassen met singletons. Ik zou zelf een instantie aanmaken op het moment dat een thread aan een bepaalde actie begint, en dit opslaan in een threadlocal of gewoon meesturen met de calls.

[ Voor 14% gewijzigd door Alarmnummer op 01-02-2007 10:01 ]


  • JKVA
  • Registratie: Januari 2004
  • Niet online

JKVA

Design-by-buzzword fanatic

Voorbeeld van Hibernate.

http://www.hibernate.org/207.html

Hier bewaren ze de huidige sessie in een ThreadLocal.

Fat Pizza's pizza, they are big and they are cheezy


  • -FoX-
  • Registratie: Januari 2002
  • Niet online

-FoX-

Carpe Diem!

FallenAngel666 schreef op donderdag 01 februari 2007 @ 09:36:
Volatile variabelen worden niet in registers gecached en zijn niet per definitie een thread safety garantie, want ze kunnen alleen het visibility aspect garanderen. Volgens het boek dat ik al eerder aanhaalde kan je volatile alleen toepassen als je aan de volgende eisen voldoet:
Ok, bedankt voor de verheldering..

In welke gevallen is het dan wel nuttig om volatile toe te passen? Enkel om reordering te voorkomen?

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

-FoX- schreef op donderdag 01 februari 2007 @ 12:06:
[...]

Ok, bedankt voor de verheldering..

In welke gevallen is het dan wel nuttig om volatile toe te passen? Enkel om reordering te voorkomen?
En om er voor te zorgen dat wijzigingen die worden gedaan op een variable ook zichtbaar zijn binnen andere threads :) Anders loop je de kans dat threads uit hun cache (of registers) gaan lezen en wijzigingen van andere threads nooit zien.

vb:

Java:
1
2
3
4
5
6
7
8
9
10
class SomeRunnable implements Runnable{
     boolean stop = false;
   
  void stop(){stop = true;}

    void run(){
     while(!stop)
        println("hallo");
    }
}


Dit is een typisch voorbeeld van een visibility probleem :) De loop zou niet hoeven te stoppen (er zijn hier trouwens 2 effecten van gebrek aan visibility die het probleem kunnen veroorzaken).

[ Voor 17% gewijzigd door Alarmnummer op 01-02-2007 12:29 ]


  • Kwistnix
  • Registratie: Juni 2001
  • Laatst online: 08:22
-FoX- schreef op donderdag 01 februari 2007 @ 12:06:
[...]

Ok, bedankt voor de verheldering..

In welke gevallen is het dan wel nuttig om volatile toe te passen? Enkel om reordering te voorkomen?
Garanderen van visibilty na het updaten van een variabele, wanneer die update niet afhankelijk is van de voorgaande waarde van die variabele en er voor de variabele geen invariant geldt waar ook andere state variabelen onderdeel van uitmaken. Allerhande 'flag' variabelen bijvoorbeeld.

Atomic load/store/read/write van 64-bit velden (long & double) afdwingen (hoewel je dan nog steeds geen long++ mag gebruiken (!) zie vorige punt).

In veel gevallen is het gebruik van volatile alleen gewoon niet genoeg en zijn de Atomic klassen uit java.util.concurrent bijvoorbeeld al snel een betere optie.

Verwijderd

maartenvdv737 schreef op donderdag 01 februari 2007 @ 09:01:
Ik ben niet zo thuis in de design patterns, maar aangezien ik hier met een third party library werk waarin ik met een hook wat dingen kan doen, heb ik dit inderdaad geprobeerd. In de thread een nieuwe instantie maken van de factory. Dit lijkt echter niet te helpen.

Ik zal eens kijken naar ThreadLocal
Ik snap niet helemaal wat er niet werkt, maar zoals ik het zie is het enige wat je hoeft te doen in je thread: "new FedQueryEngineFactory(conf);". Daarna geef je binnen die thread de instantie simpelweg door. Zo heb je helemaal geen synchronisatie nodig (als je tenminste niets engs vanuit die class doet). Tenzij je natuurlijk je fedQueryEngineFactory instanties wil behouden voor whatever reason...
Pagina: 1