Zašto ne započeti nit u konstruktoru?

1. Pregled

U ovom brzom vodiču vidjet ćemo zašto ne bismo trebali pokretati nit unutar konstruktora.

Prvo ćemo ukratko predstaviti koncept objavljivanja na Javi i JVM-u. Zatim ćemo vidjeti kako ovaj koncept utječe na način na koji započinjemo teme.

2. Objava i bijeg

Svaki put kad objekt učinimo dostupnim bilo kojem drugom kodu izvan trenutnog opsega, u osnovi ga objavljujemo. Na primjer, objavljivanje se događa kada objekt vratimo i pohranimo u javnost referencu ili je čak proslijediti drugoj metodi.

Kad objavimo objekt koji ne bismo trebali, kažemo da je objekt pobjegao.

Postoji mnogo načina na koje možemo dopustiti da referenca na objekt pobjegne, poput objavljivanja predmeta prije njegove potpune konstrukcije. Zapravo, ovo je jedan od uobičajenih oblika bijega: kada ovaj referentni bijegovi tijekom izgradnje objekta.

Kada ovaj referenca bježi tijekom gradnje, druge niti mogu vidjeti taj objekt u nepropisnom i nedovoljno izgrađenom stanju. To, pak, može prouzročiti čudne komplikacije zbog sigurnosti navoja.

3. Bijeg s nitima

Jedan od najčešćih načina dopuštanja ovaj referentni pobjeg je pokretanje niti u konstruktoru. Da bismo ovo bolje razumjeli, razmotrimo primjer:

javna klasa LoggerRunnable implementira Runnable {public LoggerRunnable () {Thread thread = new Thread (this); // ovo bježi od thread.start (); } @Override public void run () {System.out.println ("Started ..."); }}

Ovdje izričito donosimo ovaj referenca na Nit konstruktor. Stoga, novopokrenuta nit možda će moći vidjeti objekt koji obuhvaća prije dovršetka njegove potpune konstrukcije. U istodobnim kontekstima to može uzrokovati suptilne bugove.

Također je moguće proći ovaj referenca implicitno:

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

Kao što je gore prikazano, stvaramo anonimnu unutarnju klasu izvedenu iz Nit. Budući da unutarnje klase održavaju referencu na svoju zatvorenu klasu, ovaj referenca opet bježi iz konstruktora.

Ništa suštinski nije loše u stvaranju a Nit unutar konstruktora. Međutim, krajnje je obeshrabreno odmah ga pokrenuti, kao i većinu vremena, na kraju imamo pobjegle ovaj referenca, bilo eksplicitno ili implicitno.

3.1. Alternative

Umjesto pokretanja niti unutar konstruktora, možemo proglasiti namjensku metodu za ovaj scenarij:

javna klasa SafePublication implementira Runnable {private final Thread thread; javna SafePublication () {thread = nova nit (ovo); } @Override public void run () {System.out.println ("Started ..."); } javni void start () {thread.start (); }} ;:

Kao što je gore prikazano, i dalje objavljujemo ovaj referenca na Nit. Međutim, ovaj put započinjemo nit nakon što se konstruktor vrati:

Publikacija SafePublication = nova SafePublication (); publication.start ();

Stoga referenca objekta ne bježi u drugu nit prije svoje potpune konstrukcije.

4. Zaključak

U ovom smo brzom vodiču, nakon kratkog uvoda u sigurnu publikaciju, vidjeli zašto ne bismo trebali pokrenuti nit unutar konstruktora.

Detaljnije informacije o objavljivanju i bijegu na Javi mogu se naći u knjizi Java Concurrency in Practice.

Kao i obično, svi su primjeri dostupni na GitHubu.


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