Multithreading menggantikan pemrograman event loop dengan membagi task dari anda menjadi satuan yang diskret dan logis. Thread juga menyediakan sebuah keuntungan sekunder: mereka menyingkirkan dengan polling. Polling biasanya diimplementasikan dengan sebuah loop yang digunakan untuk memeriksa beberapa kondisi secara berulang. Sekali kondisi benar, tindakan yang tepat diambil. Hal ini menyia-nyiakan jatah waktu CPU. Sebagai contoh, bayangkan permasalahan antrian klasik, dimana satu thread menghasilkan data dan lainnya menggunakannya. Untuk membuat permasalahan tersebut semakin menarik, misalkan producer harus menunggu konsumen selesai sebelum produser menghasilkan lebih banyak data. Dalam sebuah sistem polling, consumer akan membuang banyak siklus CPU ketika consumer menunggu produser untuk memproduksi. Ketika, produser selesai, produser akan memulai polling, yang membuang lebih banyak siklus CPU yang menunggu konsumen selesai, dan seterusnya. Secara jelas, situasi ini tidak diinginkan.
Untuk menghindari polling, Java memuat sebuah mekanisme interprocess communication yang elegan melalui method wait(), notify(), dan notifyAll(). Method ini diimplementasikan sebagai method final dalam Object, sehingga semua class mempunyai semua method tersebut. Semua ketiga method bisa dipanggil hanya dalam sebuah method synchronized. Walaupun secara lebih konsep lanjut, dari sebuah sudut pandang ilmu komputer, aturan untuk penggunaan method-method ini secara actual cukup sederhana:
- wait() menyatakan thread yang memanggil menyerahkan monitor dan menjadi sleep sampai beberapa thread masuk monitor yang sama dan memanggil notify().
- notify() membangunkan thread pertama yang telah memanggil wait() pada object yang sama.
- notifyAll() membangunkan semua thread yang telah memanggil wait() pada object yang sama. Prioritas thread tertinggi akan berjalan pertama kali.
Method-method ini dideklarasikan dalam Object, seperti yang ditunjukkan berikut:
final void wait( ) throws InterruptedException
final void notify( )
final void notifyAll( )
Bentuk tambahan untuk wait() hadir yang memungkinkan anda untuk menentukan sebuah periode waktu untuk menunggu. Contoh program berikut secara tidak tepat mengimplementasikan sebuah bentuk sederhana dari permasalahan producer/consumer. Program tersebut terdiri atas empat class: Q, antrian yang and coba untuk singkronisasikan, Producer, object yang dithreadkan yang menghasilkan masukan untuk antrian; Consumer, object yang dithreadkan yang mengkonsumsi masukan antrian dan PC class kecil yang menghasilkan Q, Producer, dan Consumer tunggal.
package prodcons;Walaupun method put() dan get() pada Q tersingkronisasi, tidak ada yang menghentikan producer dari membanjiri konsumen, tidak pula akan ada sesuatu yang menghentikan konsumen dari megkonsumsi antrian nilai yang sama dua kali. Oleh karena itu, anda mendapatkan kesalahan output yang ditunjukkan di sini (keluaran yang tepat akan bervariasi dengan kecepatan prosesor dan beban task):
// An incorrect implementation of a producer and consumer.
class Q {
int n;
synchronized int get() {
System.out.println("Got: " + n);
return n;
}
synchronized void put(int n) {
this.n = n;
System.out.println("Put: " + n);
}
}
class Producer implements Runnable {
Q q;
Producer(Q q) {
this.q = q;
new Thread(this, "Producer").start();
}
public void run() {
int i = 0;
while (true) {
q.put(i++);
}
}
}
class Consumer implements Runnable {
Q q;
Consumer(Q q) {
this.q = q;
new Thread(this, "Consumer").start();
}
public void run() {
while (true) {
q.get();
}
}
}
class PC {
public static void main(String args[]) {
Q q = new Q();
new Producer(q);
new Consumer(q);
System.out.println("Press Control-C to stop.");
}
}
Put: 1
Got: 1
Got: 1
Got: 1
Got: 1
Got: 1
Put: 2
Put: 3
Put: 4
Put: 5
Put: 6
Put: 7
Got: 7
Seperti yang anda lihat setelah, produser meletakkan 1, konsumen mulai dan mendapatkan 1 lima kali secara beruntun. Kemudian, produser melanjutkan dan memproduksi 2 sampai 7 tanpa membiarkan mempunyai sebuah kesempatan untuk mengkonsumsinya.
Cara yang tepat untuk menuliskan program ini dalam Java yaitu dengan menggunakan wait() dan notify() pada sinyal ke dua arah seperti yang ditunjukkan berikut:
// A correct implementation of a producer and consumer.Dalam get(), wait() dipanggil. Hal ini menyebabkan eksekusinya ditunda sampai Producer melakukan notify() bahwa beberapa data telah siap. Ketika hal ini terjadi, eksekusi get() berlanjut. Setelah data telah diperoleh get() memanggil notify(). Hal ini mengatakan bahwa Producer bahwa tidak apa-apa untuk meletakkan lebih banyak data dalam antrian. Di dalam put(), wait() menunda eksekusi sampai Consumer telah memindahkan item dari antrian. Ketika eksekusi lanjut, item berikutnya diletakkan dalam antrian, dan notify() dipanggil. Hal ini mengatakan bahwa Consumer bahwa seharusnya sekarang memindahkan data tersebut.
class Q {
int n;
boolean valueSet = false;
synchronized int get() {
if (!valueSet) {
try {
wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
}
System.out.println("Got: " + n);
valueSet = false;
notify();
return n;
}
synchronized void put(int n) {
if (valueSet) {
try {
wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
}
this.n = n;
valueSet = true;
System.out.println("Put: " + n);
notify();
}
}
class Producer implements Runnable {
Q q;
Producer(Q q) {
this.q = q;
new Thread(this, "Producer").start();
}
public void run() {
int i = 0;
while (true) {
q.put(i++);
}
}
}
class Consumer implements Runnable {
Q q;
Consumer(Q q) {
this.q = q;
new Thread(this, "Consumer").start();
}
public void run() {
while (true) {
q.get();
}
}
}
class PCFixed {
public static void main(String args[]) {
Q q = new Q();
new Producer(q);
new Consumer(q);
System.out.println("Press Control-C to stop.");
}
}
Berikut adalah keluaran dari program, yang mana menunjukkan perilaku sinkronisasi yang halus.
Put: 1
Got: 1
Put: 2
Got: 2
Put: 3
Got: 3
Put: 4
Got: 4
Put: 5
Got: 5
Tutorial ini diambil dari buku "The complete Reference Java 2" oleh Herbert Schildt dan http://www.java-samples.com/showtutorial.php?tutorialid=306
kontennya bagus, thanks
ReplyDelete