CodeGym /Blog Jawa /Acak /Luwih apik bebarengan: Jawa lan kelas Utas. Bagean II - S...
John Squirrels
tingkat
San Francisco

Luwih apik bebarengan: Jawa lan kelas Utas. Bagean II - Sinkronisasi

Diterbitake ing grup

Pambuka

Dadi, kita ngerti yen Jawa duwe benang. Sampeyan bisa maca babagan kasebut ing review kanthi irah-irahan Better together: Java and the Thread class. Bagian I - Utas eksekusi . Utas perlu kanggo nindakake karya kanthi paralel. Iki nggawe kemungkinan banget yen benang bakal sesambungan karo siji liyane. Ayo goleki kepiye kedadeyan lan alat dhasar apa sing kita duwe. Luwih apik bebarengan: Jawa lan kelas Utas.  Bagean II - Sinkronisasi - 1

ngasilaken

Thread.yield () baffling lan arang digunakake. Iki diterangake ing macem-macem cara ing Internet. Kalebu sawetara wong sing nulis yen ana sawetara antrian utas, ing ngendi utas bakal mudhun adhedhasar prioritas utas. Wong liya nulis yen thread bakal ngganti statuse saka "Mlaku" dadi "Mlaku" (sanajan ora ana bedane antarane status kasebut, yaiku Jawa ora mbedakake antarane). Kasunyatan iku kabeh kurang kondhang lan durung prasaja ing pangertèn. Luwih apik bebarengan: Jawa lan kelas Utas.  Bagean II - Sinkronisasi - 2Ana bug ( JDK-6416721: (spec thread) Ndandani Thread.yield() javadoc ) mlebu kanggo yield()dokumentasi cara. Yen sampeyan maca, iku cetha singyield()cara bener mung menehi sawetara Rekomendasi kanggo Java thread scheduler sing thread iki bisa diwenehi wektu eksekusi kurang. Nanging apa bener mengkono, IE apa panjadwal tumindak ing Rekomendasi lan apa ing umum, gumantung ing implementasine JVM lan sistem operasi. Lan bisa uga gumantung ing sawetara faktor liyane. Kabeh kebingungan iki paling kamungkinan amarga kasunyatan sing multithreading wis rethought minangka basa Jawa wis berkembang. Waca liyane ing ringkesan kene: Brief Pambuka kanggo Java Thread.yield () .

Turu

Utas bisa turu sajrone eksekusi. Iki minangka jinis interaksi sing paling gampang karo benang liyane. Sistem operasi sing nganggo mesin virtual Java sing nganggo kode Java kita duwe panjadwal thread dhewe . Iku nemtokaken thread kanggo miwiti lan nalika. Programmer ora bisa sesambungan karo panjadwal iki langsung saka kode Jawa, mung liwat JVM. Dheweke bisa njaluk panjadwal kanggo ngaso thread kanggo sawetara wektu, yaiku supaya turu. Sampeyan bisa maca liyane ing artikel iki: Thread.sleep () lan carane Multithreading dianggo . Sampeyan uga bisa mriksa carane thread bisa digunakake ing sistem operasi Windows: Internal Windows Thread . Lan saiki ayo padha ndeleng kanthi mripat dhewe. Simpen kode ing ngisor iki ing file sing jenenge HelloWorldApp.java:

class HelloWorldApp {
    public static void main(String []args) {
        Runnable task = () -> {
            try {
                int secToWait = 1000 * 60;
                Thread.currentThread().sleep(secToWait);
                System.out.println("Woke up");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        Thread thread = new Thread(task);
        thread.start();
    }
}
Nalika sampeyan bisa ndeleng, kita duwe sawetara tugas sing ngenteni 60 detik, sawise program rampung. Kita ngumpulake nggunakake printah " javac HelloWorldApp.java" banjur mbukak program nggunakake " java HelloWorldApp". Iku paling apik kanggo miwiti program ing jendhela kapisah. Contone, ing Windows, kaya iki: start java HelloWorldApp. Kita nggunakake printah jps kanggo njaluk PID (ID proses), lan kita mbukak dhaptar utas nganggo " jvisualvm --openpid pid: Luwih apik bebarengan: Jawa lan kelas Utas.  Bagean II - Sinkronisasi - 3Kaya sing sampeyan deleng, thread kita saiki duwe status "Sleeping". Nyatane, ana cara sing luwih elegan kanggo mbantu. thread kita duwe mimpi manis:

try {
	TimeUnit.SECONDS.sleep(60);
	System.out.println("Woke up");
} catch (InterruptedException e) {
	e.printStackTrace();
}
Apa sampeyan ngerti yen kita lagi nangani InterruptedExceptioning endi wae? Ayo padha ngerti sebabe.

Thread.interrupt()

Masalahe, nalika ana thread nunggu / turu, ana sing pengin ngganggu. Ing kasus iki, kita nangani a InterruptedException. Mekanisme iki digawe sawise Thread.stop()cara kasebut diumumake Ditinggalake, yaiku ketinggalan jaman lan ora dikarepake. Alesane yaiku nalika stop()metode kasebut diarani, benang kasebut mung "dipateni", sing ora bisa ditebak. Kita ora bisa ngerti kapan thread bakal mandheg, lan kita ora bisa njamin konsistensi data. Bayangake yen sampeyan nulis data menyang file nalika benang mati. Tinimbang mateni utas, pangripta Jawa mutusake manawa luwih logis yen ujar manawa kudu diselani. Kepiye carane nanggapi informasi kasebut minangka prakara sing kudu diputusake dhewe. Kanggo rincian liyane, waca Napa Thread.stop ora digunakake?ing situs web Oracle. Ayo katon ing conto:

public static void main(String []args) {
	Runnable task = () -> {
		try {
			TimeUnit.SECONDS.sleep(60);
		} catch (InterruptedException e) {
			System.out.println("Interrupted");
		}
	};
	Thread thread = new Thread(task);
	thread.start();
	thread.interrupt();
}
Ing conto iki, kita ora bakal ngenteni 60 detik. Nanging, kita bakal langsung nampilake "Interrupted". Iki amarga kita disebut interrupt()cara ing thread. Cara iki nyetel gendera internal sing diarani "status interupsi". Tegese, saben thread duwe gendera internal sing ora bisa diakses langsung. Nanging kita duwe cara asli kanggo sesambungan karo gendera iki. Nanging iki ora mung cara. Utas bisa mlaku, ora ngenteni apa-apa, mung nindakake tumindak. Nanging bisa uga ngarepake manawa wong liya pengin mungkasi karya kasebut ing wektu tartamtu. Tuladhane:

public static void main(String []args) {
	Runnable task = () -> {
		while(!Thread.currentThread().isInterrupted()) {
			// Do some work
		}
		System.out.println("Finished");
	};
	Thread thread = new Thread(task);
	thread.start();
	thread.interrupt();
}
Ing conto ing ndhuwur, whiledaur ulang bakal dieksekusi nganti thread diselani externally. Minangka kanggo isInterruptedflag, iku penting kanggo ngerti yen kita nyekel InterruptedException, flag isInterrupted bakal ngreset, banjur isInterrupted()bakal bali palsu. Kelas Utas uga wis Thread.interrupted statis () cara sing mung ditrapake kanggo Utas saiki, nanging cara iki ngreset flag palsu! Waca liyane ing bab iki kanthi judhul Gangguan Utas .

Gabung (Ngenteni thread liyane rampung)

Jinis nunggu sing paling gampang yaiku ngenteni thread liyane rampung.

public static void main(String []args) throws InterruptedException {
	Runnable task = () -> {
		try {
			TimeUnit.SECONDS.sleep(5);
		} catch (InterruptedException e) {
			System.out.println("Interrupted");
		}
	};
	Thread thread = new Thread(task);
	thread.start();
	thread.join();
	System.out.println("Finished");
}
Ing conto iki, utas anyar bakal turu 5 detik. Ing wektu sing padha, benang utama bakal ngenteni nganti benang turu tangi lan rampung karyane. Yen sampeyan ndeleng kahanan thread ing JVisualVM, bakal katon kaya iki: Luwih apik bebarengan: Jawa lan kelas Utas.  Bagean II - Sinkronisasi - 4Thanks kanggo alat ngawasi, sampeyan bisa ndeleng apa sing kedadeyan karo benang kasebut. Cara iki joincukup prasaja, amarga mung cara nganggo kode Jawa sing dieksekusi wait()anggere thread sing diarani isih urip. Sanalika benang mati (yen wis rampung karo karyane), ngenteni diselani. Lan iki kabeh keajaiban metode kasebut join(). Dadi, ayo pindhah menyang sing paling menarik.

Ngawasi

Multithreading kalebu konsep monitor. Tembung monitor asalé saka basa Inggris nganggo basa Latin abad kaping 16 lan tegesé "instrumen utawa piranti sing digunakake kanggo ngamati, mriksa, utawa nyimpen rekaman terus-terusan saka sawijining proses". Ing konteks artikel iki, kita bakal nyoba kanggo nutupi dhasar. Kanggo sapa wae sing pengin rincian, mangga nyilem menyang bahan sing disambung. Kita miwiti lelampahan kanthi Spesifikasi Bahasa Jawa (JLS): 17.1. Sinkronisasi . Ngandika ing ngisor iki: Luwih apik bebarengan: Jawa lan kelas Utas.  Bagean II - Sinkronisasi - 5Pranyata Jawa nggunakake mekanisme "monitor" kanggo sinkronisasi antarane Utas. Monitor digandhengake karo saben obyek, lan benang bisa ndarbeni lock()utawa ngeculake karo unlock(). Sabanjure, kita bakal nemokake tutorial ing situs web Oracle: Kunci lan Sinkronisasi Intrinsik. Tutorial iki nyatakake yen sinkronisasi Jawa dibangun ing saubengé entitas internal sing diarani kunci intrinsik utawa kunci monitor . Kunci iki asring diarani " monitor ". Kita uga ndeleng maneh manawa saben obyek ing Jawa duwe kunci intrinsik sing ana gandhengane. Sampeyan bisa maca Jawa - Kunci Intrinsik lan Sinkronisasi . Sabanjure bakal penting kanggo ngerti carane obyek ing Jawa bisa digandhengake karo monitor. Ing Jawa, saben obyek duwe header sing nyimpen metadata internal sing ora kasedhiya kanggo programmer saka kode kasebut, nanging mesin virtual kudu bisa digunakake kanthi bener karo obyek. Header obyek kalebu "tembung tandha", sing katon kaya iki: Luwih apik bebarengan: Jawa lan kelas Utas.  Bagean II - Sinkronisasi - 6

https://edu.netbeans.org/contrib/slides/java-overview-and-java-se6.pdf

Mangkene artikel JavaWorld sing migunani banget: Kepiye mesin virtual Java nindakake sinkronisasi benang . Artikel iki kudu digabungake karo katrangan saka bagean "Ringkesan" saka masalah ing ngisor iki ing sistem nelusuri bug JDK: JDK-8183909 . Sampeyan bisa maca bab sing padha kene: JEP-8183909 . Dadi, ing Jawa, monitor digandhengake karo obyek lan digunakake kanggo mblokir thread nalika thread nyoba kanggo ndarbeni (utawa njaluk) kunci. Punika conto paling prasaja:

public class HelloWorld{
    public static void main(String []args){
        Object object = new Object();
        synchronized(object) {
            System.out.println("Hello World");
        }
    }
}
Ing kene, utas saiki (sing dieksekusi baris kode kasebut) nggunakake tembung synchronizedkunci kanggo nyoba nggunakake monitor sing ana gandhengane karoobject"\variabel kanggo njaluk / entuk kunci. Yen ora ana wong liya sing saingan kanggo monitor (yaiku ora ana wong liya sing nglakokake kode sing disinkronake kanthi nggunakake obyek sing padha), banjur Jawa bisa nyoba nindakake optimasi sing diarani "pengunci bias". Tag sing cocog lan cathetan babagan benang sing duwe kunci monitor ditambahake ing tembung tandha ing header obyek. Iki nyuda overhead sing dibutuhake kanggo ngunci monitor. Yen monitor sadurunge diduweni dening thread liyane, ngunci kuwi ora cukup. JVM ngalih menyang jinis ngunci sabanjure: "ngunci dhasar". Iki nggunakake operasi comparison-and-swap (CAS). Apa maneh, tembung tandha obyek header dhewe ora nyimpen tembung tandha, nanging minangka referensi ing ngendi disimpen, lan tag diganti supaya JVM ngerti yen kita nggunakake kunci dhasar. Yen sawetara benang saingan (saingan) kanggo monitor (siji wis entuk kunci, lan liyane ngenteni kunci diluncurake), banjur tag ing tembung tandha ganti, lan tembung tandha saiki nyimpen referensi menyang monitor. minangka obyek - sawetara entitas internal JVM. Kaya sing kasebut ing JDK Enchancement Proposal (JEP), kahanan iki mbutuhake papan ing area memori Native Heap kanggo nyimpen entitas iki. Referensi kanggo lokasi memori entitas internal iki bakal disimpen ing tembung tandha header obyek. Mangkono, monitor pancene minangka mekanisme kanggo nyinkronake akses menyang sumber daya sing dienggo bareng ing pirang-pirang utas. JVM ngalih ing antarane sawetara implementasi mekanisme iki. Dadi, kanggo gamblang, nalika ngomong babagan monitor, kita bener-bener ngomong babagan kunci. lan kapindho nunggu kunci kanggo dirilis), banjur tag ing tandha tembung ganti, lan tembung tandha saiki nyimpen referensi kanggo monitor minangka obyek - sawetara entitas internal JVM. Kaya sing kasebut ing JDK Enchancement Proposal (JEP), kahanan iki mbutuhake papan ing area memori Native Heap kanggo nyimpen entitas iki. Referensi kanggo lokasi memori entitas internal iki bakal disimpen ing tembung tandha header obyek. Mangkono, monitor pancene minangka mekanisme kanggo nyinkronake akses menyang sumber daya sing dienggo bareng ing pirang-pirang utas. JVM ngalih ing antarane sawetara implementasi mekanisme iki. Dadi, kanggo gamblang, nalika ngomong babagan monitor, kita bener-bener ngomong babagan kunci. lan kapindho nunggu kunci kanggo dirilis), banjur tag ing tandha tembung ganti, lan tembung tandha saiki nyimpen referensi kanggo monitor minangka obyek - sawetara entitas internal JVM. Kaya sing kasebut ing JDK Enchancement Proposal (JEP), kahanan iki mbutuhake papan ing area memori Native Heap kanggo nyimpen entitas iki. Referensi kanggo lokasi memori entitas internal iki bakal disimpen ing tembung tandha header obyek. Mangkono, monitor pancene minangka mekanisme kanggo nyinkronake akses menyang sumber daya sing dienggo bareng ing pirang-pirang utas. JVM ngalih ing antarane sawetara implementasi mekanisme iki. Dadi, kanggo gamblang, nalika ngomong babagan monitor, kita bener-bener ngomong babagan kunci. lan tembung tandha saiki nyimpen referensi kanggo monitor minangka obyek - sawetara entitas internal JVM. Kaya sing kasebut ing JDK Enchancement Proposal (JEP), kahanan iki mbutuhake papan ing area memori Native Heap kanggo nyimpen entitas iki. Referensi kanggo lokasi memori entitas internal iki bakal disimpen ing tembung tandha header obyek. Mangkono, monitor pancene minangka mekanisme kanggo nyinkronake akses menyang sumber daya sing dienggo bareng ing pirang-pirang utas. JVM ngalih ing antarane sawetara implementasi mekanisme iki. Dadi, kanggo gamblang, nalika ngomong babagan monitor, kita bener-bener ngomong babagan kunci. lan tembung tandha saiki nyimpen referensi kanggo monitor minangka obyek - sawetara entitas internal JVM. Kaya sing kasebut ing JDK Enchancement Proposal (JEP), kahanan iki mbutuhake papan ing area memori Native Heap kanggo nyimpen entitas iki. Referensi kanggo lokasi memori entitas internal iki bakal disimpen ing tembung tandha header obyek. Mangkono, monitor pancene minangka mekanisme kanggo nyinkronake akses menyang sumber daya sing dienggo bareng ing pirang-pirang utas. JVM ngalih ing antarane sawetara implementasi mekanisme iki. Dadi, kanggo gamblang, nalika ngomong babagan monitor, kita bener-bener ngomong babagan kunci. Referensi kanggo lokasi memori entitas internal iki bakal disimpen ing tembung tandha header obyek. Mangkono, monitor pancene minangka mekanisme kanggo nyinkronake akses menyang sumber daya sing dienggo bareng ing pirang-pirang utas. JVM ngalih ing antarane sawetara implementasi mekanisme iki. Dadi, kanggo gamblang, nalika ngomong babagan monitor, kita bener-bener ngomong babagan kunci. Referensi kanggo lokasi memori entitas internal iki bakal disimpen ing tembung tandha header obyek. Mangkono, monitor pancene minangka mekanisme kanggo nyinkronake akses menyang sumber daya sing dienggo bareng ing pirang-pirang utas. JVM ngalih ing antarane sawetara implementasi mekanisme iki. Dadi, kanggo gamblang, nalika ngomong babagan monitor, kita bener-bener ngomong babagan kunci. Luwih apik bebarengan: Jawa lan kelas Utas.  Bagean II - Sinkronisasi - 7

Disinkronake (ngenteni kunci)

Kaya sing wis dingerteni sadurunge, konsep "blok sing disinkronake" (utawa "bagian kritis") ana hubungane karo konsep monitor. Delengen contone:

public static void main(String[] args) throws InterruptedException {
	Object lock = new Object();

	Runnable task = () -> {
		synchronized(lock) {
			System.out.println("thread");
		}
	};

	Thread th1 = new Thread(task);
	th1.start();
	synchronized(lock) {
		for (int i = 0; i < 8; i++) {
			Thread.currentThread().sleep(1000);
			System.out.print(" " + i);
		}
		System.out.println(" ...");
	}
}
Ing kene, utas utama pisanan ngliwati obyek tugas menyang benang anyar, banjur langsung entuk kunci lan nindakake operasi sing dawa (8 detik). Kabeh wektu iki, tugas ora bisa diterusake, amarga ora bisa mlebu blok synchronized, amarga kunci wis entuk. Yen benang ora bisa ngunci, bakal ngenteni monitor. Sanalika entuk kunci, bakal terus eksekusi. Nalika thread metu saka monitor, iku ngeculake kunci. Ing JVisualVM, katon kaya iki: Luwih apik bebarengan: Jawa lan kelas Utas.  Bagean II - Sinkronisasi - 8Kaya sing sampeyan deleng ing JVisualVM, status kasebut "Monitor", tegese benang diblokir lan ora bisa njupuk monitor. Sampeyan uga bisa nggunakake kode kanggo nemtokake status thread, nanging jeneng status sing ditemtokake kanthi cara iki ora cocog karo jeneng sing digunakake ing JVisualVM, sanajan padha. Ing kasus iki, ingth1.getState()statement ing kanggo daur ulang bakal bali BLOCKED , amarga anggere daur ulang mlaku, lockmonitor obyek dikuwasani dening mainthread, lan th1thread diblokir lan ora bisa nerusake nganti kunci dirilis. Saliyane pamblokiran sing disinkronake, kabeh cara bisa disinkronake. Contone, iki cara saka kelas HashTable:

public synchronized int size() {
	return count;
}
Cara iki bakal dileksanakake mung siji thread ing sembarang wektu tartamtu. Apa kita pancene butuh kunci? Ya, kita butuh. Ing kasus cara conto, obyek "iki" (obyek saiki) tumindak minangka kunci. Ana diskusi menarik babagan topik iki: Apa ana kauntungan kanggo nggunakake Metode sing disinkronake tinimbang Blok sing disinkronake? . Yen cara statis, kunci ora bakal dadi obyek "iki" (amarga ora ana obyek "iki" kanggo metode statis), nanging obyek Kelas (contone, Integer.class).

Ngenteni (ngenteni monitor). notify () lan notifyAll () metode

Kelas Utas duwe cara nunggu liyane sing digandhengake karo monitor. Ora kaya sleep()lan join(), cara iki ora bisa diarani mung. jenenge wait(). Cara kasebut waitdiarani obyek sing digandhengake karo monitor sing arep kita tunggu. Ayo ndeleng conto:

public static void main(String []args) throws InterruptedException {
	    Object lock = new Object();
	    // The task object will wait until it is notified via lock
	    Runnable task = () -> {
	        synchronized(lock) {
	            try {
	                lock.wait();
	            } catch(InterruptedException e) {
	                System.out.println("interrupted");
	            }
	        }
	        // After we are notified, we will wait until we can acquire the lock
	        System.out.println("thread");
	    };
	    Thread taskThread = new Thread(task);
	    taskThread.start();
        // We sleep. Then we acquire the lock, notify, and release the lock
	    Thread.currentThread().sleep(3000);
	    System.out.println("main");
	    synchronized(lock) {
	        lock.notify();
	    }
}
Ing JVisualVM, katon kaya iki: Luwih apik bebarengan: Jawa lan kelas Utas.  Bagean II - Sinkronisasi - 10Kanggo ngerti cara kerjane, elinga yen metode wait()lan notify()digandhengake karo java.lang.Object. Koyone aneh yen metode sing ana gandhengane karo benang ana ing Objectkelas. Nanging alesan kanggo sing saiki unfolds. Sampeyan bakal kelingan manawa saben obyek ing Jawa duwe header. Header ngemot macem-macem informasi housekeeping, kalebu informasi babagan monitor, yaiku status kunci. Elinga, saben obyek, utawa conto kelas, digandhengake karo entitas internal ing JVM, sing diarani kunci utawa monitor intrinsik. Ing conto ing ndhuwur, kode kanggo obyek tugas nuduhake yen kita mlebu blok sing disinkronake kanggo monitor sing ana gandhengane karo lockobyek kasebut. Yen kita kasil entuk kunci kanggo monitor iki, banjurwait()diarani. Utas sing nglakokake tugas bakal ngeculake lockmonitor obyek, nanging bakal mlebu antrian benang nunggu kabar saka lockmonitor obyek. Antrian utas iki diarani WAIT SET, sing luwih nggambarake tujuane. Sing, iku luwih saka pesawat saka antrian. Utas mainnggawe utas anyar kanthi obyek tugas, diwiwiti, lan ngenteni 3 detik. Iki ndadekake banget kamungkinan sing thread anyar bakal bisa kanggo ndarbeni kunci sadurunge thread main, lan njaluk menyang antrian monitor. Sawisé iku, mainthread dhewe mlebu lockblok sing disinkronake obyek lan nindakake kabar thread nggunakake monitor. Sawise kabar kasebut dikirim, mainthread kasebut ngeculakelockmonitor obyek, lan Utas anyar, kang sadurunge nunggu lockmonitor obyek kang dirilis, terus eksekusi. Sampeyan bisa ngirim kabar mung siji utas ( notify()) utawa bebarengan kanggo kabeh utas ing antrian ( notifyAll()). Waca liyane kene: Bedane antarane notify () lan notifyAll () ing Jawa . Wigati dimangerteni manawa pesenan kabar gumantung saka cara JVM dileksanakake. Waca liyane ing kene: Kepiye cara ngatasi keluwen kanthi notify lan notifyAll? . Sinkronisasi bisa ditindakake tanpa nemtokake obyek. Sampeyan bisa nindakake iki nalika kabeh cara disinkronake tinimbang siji blok kode. Contone, kanggo metode statis, kunci bakal dadi obyek Kelas (dipikolehi liwat .class):

public static synchronized void printA() {
	System.out.println("A");
}
public static void printB() {
	synchronized(HelloWorld.class) {
		System.out.println("B");
	}
}
Ing babagan nggunakake kunci, loro cara kasebut padha. Yen cara ora statis, sinkronisasi bakal ditindakake kanthi nggunakake arus instance, yaiku nggunakake this. Miturut cara, kita ngandika sadurungé sampeyan bisa nggunakake getState()cara kanggo njaluk status thread. Contone, kanggo thread ing antrian nunggu monitor, status bakal WAITING utawa TIMED_WAITING, yen wait()cara kasebut wektu entek. Luwih apik bebarengan: Jawa lan kelas Utas.  Bagean II — Sinkronisasi - 11

https://stackoverflow.com/questions/36425942/what-is-the-lifecycle-of-thread-in-java

Siklus urip thread

Sajrone urip, status thread diganti. Nyatane, owah-owahan kasebut kalebu siklus urip benang. Sanalika thread digawe, statuse NEW. Ing negara iki, utas anyar durung mlaku lan panjadwal thread Jawa durung ngerti apa-apa. Supaya penjadwal thread sinau babagan utas, sampeyan kudu nelpon thread.start()cara kasebut. Banjur thread bakal transisi menyang negara RUNNABLE. Internet duwe akeh diagram sing ora bener sing mbedakake antarane negara "Runnable" lan "Running". Nanging iki salah, amarga Jawa ora mbedakake antarane "siap kerja" (runnable) lan "makarya" (mlaku). Nalika thread urip nanging ora aktif (ora Runnable), ana ing salah siji saka rong negara:
  • BLOCKED — ngenteni mlebu bagean kritis, yaiku synchronizedblok.
  • WAITING — ngenteni thread liyane kanggo marem sawetara kondisi.
Yen kondisi wis wareg, banjur jadwal thread miwiti thread. Yen thread ngenteni nganti wektu sing ditemtokake, statuse TIMED_WAITING. Yen utas ora mlaku maneh (wis rampung utawa pengecualian dibuwang), banjur mlebu status TERMINATED. Kanggo ngerteni kahanan thread, gunakake getState()metode kasebut. Utas uga duwe isAlive()metode, sing ngasilake bener yen benang ora DIPUTUSake.

LockSupport lan parkir Utas

Diwiwiti karo Java 1.6, mekanisme menarik sing diarani LockSupport muncul. Luwih apik bebarengan: Jawa lan kelas Utas.  Bagean II — Sinkronisasi - 12Kelas iki nggandhengake "ijin" karo saben utas sing nggunakake. Telpon kanggo park()cara bali langsung yen ijin kasedhiya, akeh ijin ing proses. Yen ora, iku pamblokiran. Nelpon unparkcara nggawe ijin kasedhiya yen durung kasedhiya. Mung ana 1 ijin. Dokumentasi Jawa kanggo LockSupportnuduhake kelas Semaphore. Ayo katon ing conto prasaja:

import java.util.concurrent.Semaphore;
public class HelloWorldApp{
    
    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(0);
        try {
            semaphore.acquire();
        } catch (InterruptedException e) {
            // Request the permit and wait until we get it
            e.printStackTrace();
        }
        System.out.println("Hello, World!");
    }
}
Kode iki bakal tansah ngenteni, amarga saiki semaphore wis 0 ijin. Lan nalika acquire()disebut ing kode (ie njaluk ijin), thread ngenteni nganti nampa ijin. Amarga kita ngenteni, kita kudu nangani InterruptedException. Apike, semafor entuk negara benang sing kapisah. Yen kita katon ing JVisualVM, kita bakal weruh sing negara ora "Ngenteni", nanging "Park". Luwih apik bebarengan: Jawa lan kelas Utas.  Bagean II — Sinkronisasi - 13Ayo ndeleng conto liyane:

public static void main(String[] args) throws InterruptedException {
        Runnable task = () -> {
            // Park the current thread
            System.err.println("Will be Parked");
            LockSupport.park();
            // As soon as we are unparked, we will start to act
            System.err.println("Unparked");
        };
        Thread th = new Thread(task);
        th.start();
        Thread.currentThread().sleep(2000);
        System.err.println("Thread state: " + th.getState());
        
        LockSupport.unpark(th);
        Thread.currentThread().sleep(2000);
}
Status thread bakal NUNGGU, nanging JVisualVM mbedakake antarane waittembung synchronizedkunci lan parksaka LockSupportkelas. Yagene iki LockSupportpenting banget? Kita nguripake maneh menyang dokumentasi Jawa lan katon ing negara thread WAITING . Nalika sampeyan bisa ndeleng, mung ana telung cara kanggo njaluk menyang. Loro cara kasebut yaiku wait()lan join(). Lan katelu yaiku LockSupport. Ing Jawa, kunci uga bisa dibangun ing LockSupport lan nawakake alat sing luwih dhuwur. Ayo dadi nyoba kanggo nggunakake siji. Contone, delengen ReentrantLock:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class HelloWorld{

    public static void main(String []args) throws InterruptedException {
        Lock lock = new ReentrantLock();
        Runnable task = () -> {
            lock.lock();
            System.out.println("Thread");
            lock.unlock();
        };
        lock.lock();

        Thread th = new Thread(task);
        th.start();
        System.out.println("main");
        Thread.currentThread().sleep(2000);
        lock.unlock();
    }
}
Kaya ing conto sadurunge, kabeh gampang ing kene. Obyek lockngenteni wong ngeculake sumber daya sing dienggo bareng. Yen kita ndeleng ing JVisualVM, kita bakal weruh yen thread anyar bakal diparkir nganti thread mainngeculake kunci kasebut. Sampeyan bisa maca liyane babagan kunci kene: Jawa 8 StampedLocks vs ReadWriteLocks lan Sinkronisasi lan Kunci API ing Jawa. Kanggo luwih ngerti carane kunci dileksanakake, iku mbiyantu kanggo maca babagan Phaser ing artikel iki: Pandhuan kanggo Java Phaser . Lan ngomong babagan macem-macem sinkronisasi, sampeyan kudu maca artikel DZone ing The Java Synchronizers.

Kesimpulan

Ing review iki, kita nliti cara utama sing sesambungan benang ing Jawa. Materi tambahan: Luwih apik bebarengan: Jawa lan kelas Utas. Bagian I - Utas eksekusi Luwih apik bebarengan: Jawa lan kelas Utas. Bagean III - Interaksi Better bebarengan: Jawa lan kelas Utas. Part IV - Callable, Future, lan kanca-kanca Luwih apik bebarengan: Jawa lan kelas Utas. Part V - Executor, ThreadPool, Fork / Gabung luwih apik bebarengan: Jawa lan kelas Utas. Bab VI - Mbusak!
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION