Pambuka
Utas minangka perkara sing menarik. Ing review kepungkur, kita ndeleng sawetara alat sing kasedhiya kanggo ngetrapake multithreading. Ayo ndeleng apa liyane menarik sing bisa ditindakake. Ing titik iki, kita ngerti akeh. Contone, saka "
Luwih apik bebarengan: Jawa lan kelas Utas. Part I - Utas eksekusi ", kita ngerti yen kelas Utas nggambarake benang eksekusi. Kita ngerti yen thread nindakake sawetara tugas. Yen kita pengin tugas kita bisa
run
, banjur kita kudu menehi tandha thread karo
Runnable
.
Kanggo ngelingi, kita bisa nggunakake
Tutorialspoint Online Java Compiler :
public static void main(String[] args){
Runnable task = () -> {
Thread thread = Thread.currentThread();
System.out.println("Hello from " + thread.getName());
};
Thread thread = new Thread(task);
thread.start();
}
Kita uga ngerti manawa ana sing diarani kunci. Kita sinau babagan iki ing "
Better together: Java and the Thread class. Part II — Sinkronisasi . Yen siji thread entuk kunci, banjur thread liyane sing nyoba ndarbeni kunci bakal dipeksa ngenteni kunci dibebasake:
import java.util.concurrent.locks.*;
public class HelloWorld{
public static void main(String []args){
Lock lock = new ReentrantLock();
Runnable task = () -> {
lock.lock();
Thread thread = Thread.currentThread();
System.out.println("Hello from " + thread.getName());
lock.unlock();
};
Thread thread = new Thread(task);
thread.start();
}
}
Aku mikir iki wektu kanggo ngomong bab apa menarik liyane kita bisa nindakake.
Semaphore
Cara paling gampang kanggo ngontrol pirang-pirang utas sing bisa mlaku bebarengan yaiku semafor. Iku kaya sinyal sepur. Ijo tegese nerusake. Abang tegese ngenteni. Ngenteni apa saka semafor? Akses. Kanggo entuk akses, kita kudu entuk. Lan nalika akses ora dibutuhake maneh, kita kudu menehi utawa ngeculake. Ayo ndeleng carane iki bisa. Kita kudu ngimpor
java.util.concurrent.Semaphore
kelas. Tuladha:
public static void main(String[] args) throws InterruptedException {
Semaphore semaphore = new Semaphore(0);
Runnable task = () -> {
try {
semaphore.acquire();
System.out.println("Finished");
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
};
new Thread(task).start();
Thread.sleep(5000);
semaphore.release(1);
}
Kaya sing sampeyan ngerteni, operasi kasebut (entuk lan ngeculake) mbantu kita ngerti cara kerja semafor. Sing paling penting yaiku yen kita arep entuk akses, mula semafor kudu duwe ijin sing positif. Cacah iki bisa diwiwiti menyang nomer negatif. Lan kita bisa njaluk (entuk) luwih saka 1 ijin.
CountDownLatch
Mekanisme sabanjure yaiku
CountDownLatch
. Ora kaget, iki minangka latch kanthi countdown. Ing kene kita butuh pernyataan impor sing cocog kanggo
java.util.concurrent.CountDownLatch
kelas kasebut. Iku kaya balapan mlaku, ing ngendi kabeh wong ngumpul ing garis wiwitan. Lan yen kabeh wis siyap, kabeh wong bakal nampa sinyal wiwitan bebarengan lan diwiwiti kanthi bebarengan. Tuladha:
public static void main(String[] args) {
CountDownLatch countDownLatch = new CountDownLatch(3);
Runnable task = () -> {
try {
countDownLatch.countDown();
System.out.println("Countdown: " + countDownLatch.getCount());
countDownLatch.await();
System.out.println("Finished");
} catch (InterruptedException e) {
e.printStackTrace();
}
};
for (int i = 0; i < 3; i++) {
new Thread(task).start();
}
}
Kaping pisanan, kita ngandhani kancing kasebut
countDown()
. Google nemtokake countdown minangka "tumindak ngetung angka kanthi urutan mbalikke menyang nol". Lan banjur kita marang kancing kanggo
await()
, IE ngenteni nganti counter dadi nul. Apike, iki counter siji-wektu. Dokumentasi Jawa ujar, "Yen benang kudu bola-bali ngetung kanthi cara iki, gunakake CyclicBarrier". Ing tembung liyane, yen sampeyan butuh counter bisa digunakake maneh, sampeyan kudu opsi beda
CyclicBarrier
:.
CyclicBarrier
Minangka jeneng kasebut,
CyclicBarrier
minangka alangi "bisa digunakake maneh". Kita kudu ngimpor
java.util.concurrent.CyclicBarrier
kelas kasebut. Ayo katon ing conto:
public static void main(String[] args) throws InterruptedException {
Runnable action = () -> System.out.println("On your mark!");
CyclicBarrier barrier = new CyclicBarrier(3, action);
Runnable task = () -> {
try {
barrier.await();
System.out.println("Finished");
} catch (BrokenBarrierException | InterruptedException e) {
e.printStackTrace();
}
};
System.out.println("Limit: " + barrier.getParties());
for (int i = 0; i < 3; i++) {
new Thread(task).start();
}
}
Nalika sampeyan bisa ndeleng, thread nganggo
await
cara, IE ngenteni. Ing kasus iki, nilai alangan mudhun. Barrier dianggep rusak (
barrier.isBroken()
) nalika countdown tekan nul. Kanggo ngreset alangi, sampeyan kudu nelpon
reset()
cara, kang
CountDownLatch
ora duwe.
Exchanger
Mekanisme sabanjure yaiku Exchanger. Ing konteks iki, Exchange minangka titik sinkronisasi ing ngendi owah-owahan diganti utawa diganti. Kaya sing dikarepake, an
Exchanger
minangka kelas sing nindakake ijol-ijolan utawa swap. Ayo goleki conto sing paling gampang:
public static void main(String[] args) {
Exchanger<String> exchanger = new Exchanger<>();
Runnable task = () -> {
try {
Thread thread = Thread.currentThread();
String withThreadName = exchanger.exchange(thread.getName());
System.out.println(thread.getName() + " exchanged with " + withThreadName);
} catch (InterruptedException e) {
e.printStackTrace();
}
};
new Thread(task).start();
new Thread(task).start();
}
Kene kita miwiti loro thread. Saben wong nganggo metode ijol-ijolan lan ngenteni benang liyane uga mbukak metode ijol-ijolan. Kanthi mengkono, benang-benang kasebut ngganti argumen sing dilewati. menarik. Apa ora ngelingake sampeyan soko? Iku kaya
SynchronousQueue
, kang dumunung ing jantung
CachedThreadPool
. Kanggo gamblang, iki contone:
public static void main(String[] args) throws InterruptedException {
SynchronousQueue<String> queue = new SynchronousQueue<>();
Runnable task = () -> {
try {
System.out.println(queue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
};
new Thread(task).start();
queue.put("Message");
}
Conto nuduhake yen utas anyar diwiwiti, bakal ngenteni, amarga antrian bakal kosong. Banjur benang utama nempatake senar "Pesen" menyang antrian. Apa maneh, uga bakal mandheg nganti senar iki ditampa saka antrian. Sampeyan uga bisa maca "
SynchronousQueue vs Exchanger " kanggo nggoleki liyane babagan topik iki.
Phaser
Kita wis disimpen sing paling apik kanggo pungkasan -
Phaser
. Kita kudu ngimpor
java.util.concurrent.Phaser
kelas kasebut. Ayo katon ing conto prasaja:
public static void main(String[] args) throws InterruptedException {
Phaser phaser = new Phaser();
// By calling the register method, we register the current (main) thread as a party
phaser.register();
System.out.println("Phasecount is " + phaser.getPhase());
testPhaser(phaser);
testPhaser(phaser);
testPhaser(phaser);
// After 3 seconds, we arrive at the barrier and deregister. Number of arrivals = number of registrations = start
Thread.sleep(3000);
phaser.arriveAndDeregister();
System.out.println("Phasecount is " + phaser.getPhase());
}
private static void testPhaser(final Phaser phaser) {
// We indicate that there will be a +1 party on the Phaser
phaser.register();
// Start a new thread
new Thread(() -> {
String name = Thread.currentThread().getName();
System.out.println(name + " arrived");
phaser.arriveAndAwaitAdvance(); // The threads register arrival at the phaser.
System.out.println(name + " after passing barrier");
}).start();
}
Conto nggambaraké sing nalika nggunakake
Phaser
, break alangi nalika nomer registrasi cocog nomer rawuh ing alangi. Sampeyan bisa luwih akrab
Phaser
kanthi maca
artikel GeeksforGeeks iki .
Ringkesan
Kaya sing sampeyan ngerteni saka conto kasebut, ana macem-macem cara kanggo nyinkronake benang. Sadurunge, aku nyoba ngelingi aspek multithreading. Muga-muga cicilan sadurunge ing seri iki migunani. Sawetara wong ngomong yen dalan kanggo multithreading diwiwiti kanthi buku "Java Concurrency in Practice". Sanajan dirilis ing taun 2006, wong-wong kandha yen buku kasebut cukup dhasar lan isih relevan nganti saiki. Contone, sampeyan bisa maca diskusi ing kene:
Apa "Java Concurrency In Practice" isih valid? . Iku uga migunani kanggo maca pranala ing diskusi. Contone, ana link menyang buku
The Well-Grounded Java Developer , lan kita bakal nyebutake
bab 4. Modern concurrency . Ana uga review kabeh babagan topik iki:
Apa "Java Concurrency in Practice" Isih Berlaku Ing Era Jawa 8? Artikel kasebut uga menehi saran babagan apa sing kudu diwaca kanggo ngerti topik iki. Sawise iku, sampeyan bisa ndeleng buku sing apik kaya
OCA/OCP Java SE 8 Tes Praktek Programmer . Kita kasengsem ing akronim kapindho: OCP (Oracle Certified Professional). Sampeyan bakal nemokake tes ing "Bab 20: Java Concurrency". Buku iki nduweni pitakonan lan jawaban kanthi panjelasan. Contone:
Akeh wong sing bisa ngomong yen pitakonan iki minangka conto liyane babagan ngeling-eling metode. Ing tangan siji, ya. Ing tangan liyane, sampeyan bisa mangsuli pitakonan iki kanthi ngelingi sing
ExecutorService
jenis "upgrade" saka
Executor
. lan
Executor
Tujuane kanggo ndhelikake cara nggawe benang, nanging dudu cara utama kanggo nglakokake, yaiku, miwiti obyek
Runnable
ing benang anyar. Mulane ora ana
execute(Callable)
- amarga ing
ExecutorService
,
Executor
mung nambah
submit()
cara sing bisa ngasilake
Future
obyek. Mesthi wae, kita bisa ngapalake dhaptar metode, nanging luwih gampang kanggo nggawe jawaban adhedhasar kawruh kita babagan sifat kelas kasebut. Lan ing ngisor iki sawetara bahan tambahan babagan topik kasebut:
Luwih apik bebarengan: Jawa lan kelas Utas. Bagian I - Utas eksekusi Luwih apik bebarengan: Jawa lan kelas Utas. Part II - Sinkronisasi 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. Bagian V - Pelaksana, ThreadPool, Fork/Join
GO TO FULL VERSION