Miért ne indíthatnánk el a szálat a konstruktorban?

1. Áttekintés

Ebben a gyors bemutatóban meg fogjuk tudni, miért ne indíthatnánk el egy szálat egy konstruktor belsejében.

Először röviden bemutatjuk a publikációs koncepciót Java-ban és JVM-ben. Majd meglátjuk, hogy ez a koncepció hogyan befolyásolja a szálak indítását.

2. Közzététel és menekülés

Minden alkalommal, amikor egy objektumot bármely más kód számára elérhetővé teszünk a jelenlegi hatókörén kívül, alapvetően közzétesszük ezt az objektumot. Például a közzététel akkor történik, amikor egy objektumot visszaküldünk, a nyilvános hivatkozást, vagy akár át is adhat egy másik módszerre.

Amikor közzéteszünk egy olyan objektumot, amiről nem kellett volna, azt mondjuk, hogy az objektum megszökött.

Sokféleképpen engedhetjük el az objektum hivatkozását, például az objektum teljes felépítése előtt közzétesszük. Valójában ez a menekülés egyik általános formája: amikor az ez a referencia megszökik a tárgyépítés során.

Amikor az ez a referencia elhagyja az építkezés során, más szálak nem megfelelő és nem teljesen felépített állapotban láthatják az objektumot. Ez viszont furcsa menetbiztonsági komplikációkat okozhat.

3. Menekülés szálakkal

Az egyik leggyakoribb módja a ez referencia menekülés egy szál elindítása egy konstruktorban. Ennek jobb megértése érdekében vegyünk egy példát:

public class LoggerRunnable megvalósítja Runnable {public LoggerRunnable () {Thread thread = new Thread (this); // ez elkerüli a szálat.start (); } @Orride public void run () {System.out.println ("Elkezdve ..."); }}

Itt kifejezetten átadjuk a ez hivatkozás a cérna konstruktőr. Ebből kifolyólag, az újonnan indított szál képes lehet látni a körülzáró objektumot, mielőtt teljes felépítése befejeződik. Ezzel párhuzamosan ez finom hibákat okozhat.

Az is átadható ez utalás implicit módon:

public class ImplicitEscape {public ImplicitEscape () {Thread t = new Thread () {@Orride public void run () {System.out.println ("Started ..."); }}; t.start (); }}

Amint a fentiekből látható, létrehozunk egy anonim belső osztályt, amely a cérna. Mivel a belső osztályok hivatkozást tartanak záró osztályukra, az ez a referencia ismét elmenekül a konstruktortól.

Az a létrehozásával nincs eleve baj cérna egy kivitelező belsejében. Nagyon bátortalan azonban azonnal elindítani, mivel legtöbbször egy szököttel végzünk ez hivatkozás, akár kifejezetten, akár implicit módon.

3.1. Alternatívák

Ahelyett, hogy szálat indítanánk egy konstruktorban, deklarálhatunk egy dedikált módszert ehhez a forgatókönyvhöz:

public class SafePublication megvalósítja Runnable {private final Thread thread; public SafePublication () {thread = new Thread (this); } @Orride public void run () {System.out.println ("Elkezdve ..."); } public void start () {thread.start (); }} ;:

Amint a fentiekből látható, továbbra is közzétesszük a ez hivatkozás a Cérna. Ezúttal azonban a szálat a konstruktő visszatérése után kezdjük:

SafePublication publikáció = new SafePublication (); kiadvány.kezdés ();

Ezért az objektumreferencia a teljes felépítése előtt nem szökik át egy másik szálra.

4. Következtetés

Ebben a gyors bemutatóban a biztonságos publikáció rövid bemutatása után megláttuk, miért ne kezdhetnénk egy szálat egy konstruktor belsejében.

Részletesebb információk a Java kiadványról és a menekülésről a Java Concurrency in Practice könyvben találhatók.

Szokás szerint az összes példa elérhető a GitHubon.


$config[zx-auto] not found$config[zx-overlay] not found