Tuesday, August 21, 2012

Penggunaan wait(), notify(), dan notifyAll() untuk Problem Producer Consumer dalam Java

Penggunaan monitor implicit dalam object Java sangat berguna, namun anda bisa mendapatkan sebuah tingkat yang lebih halus dalam pengendalian melalui komunikasi antar-process. Seperti yang akan anda lihat, khususnya ini mudah dalam Java.

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;

// 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.");
    }
}
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):
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.
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.");
    }
}
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.
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

1 comment:

Labels

AdMob Adobe Adsense Aero Buster Air Buster Airpush Al-Ghozali Amazon Appstore Amerika Android Android App Animasi apa itu App Application Arsitektur Asimetris asus AutoArtikel Bahasa Indonesia Bahasa Inggris Blogger Blogspot Browser Bus Cara akses Cara kerja cat CERN Chiper Chrome command Contoh CORBA cPanel CS3 diff Diffie-Hellman Distance Vector domain download e-book e-book Jaringan Komputer e-book Ketidaklogisan para Filsuf e-book Sistem Operasi ebook Einstein Engineering Design Process Enkripsi file Filosofi Firefox fisika Flow Control frame Game genap 2011-2012 Gerbang Quantum getaran gif Google google nexus 7 Google Play Gratis GRE grep GSM Handoff Handover head Hosting HTML5 Hypnolearning IDL IM3 IMS Interface Definition Language Internet internet dan bisnis telekomunikasi Internet Explorer iPad 3 jadwal Jaringan Jaringan Komputer Java JDBC JSP Judul Justin Bieber Kamera Kapsel Kecepatan Cahaya Ketidaklogisan Para Filsuf kisi-kisi Komputer Kriptografi LAN Linux Manajemen Manajemen Memori mediafire Memori Mesh Model View Controller MoonViewer Motivation Multicast Routing MVC MySql Near Field Communication Network Programming Neutrino New Technology File System Nilai NTFS OPERA Organisasi dan arsitektur komputer osilasi page Partai Peduli Rakyat PC pegas Pemasaran pembuat artikel Pemrograman Bahasa Tingkat Rendah Pemrograman Jaringan Pemrograman Web Penjadwalan Penyandian Perang Sipil perintah Pertukaran Kunci Photoshop PHP Physics PKS Power Point Process Producer Consumer Programming Protokol Proyek Akhir PSTN Quantum Information Quiz Quotes RAM review Ring RMI Safari Scheduling Security Sega Genesis Sejarah Servlet Shooter Simetris Singkronisasi Sistem File Sistem Koordinat Sistem Operasi slide SlideMe Socket Solaris sort source code SPIN spinner Star Studium Generale Superkonduktor Switch tablet Tahafut Al-Falasif tail TCP Terjemah test GRE Tolak Kenaikan Harga BBM Topologi Tugas Akhir tween Twitter UAS Ubuntu Ulasan Ulasan Nokia 808 PureView UNIBBA uniq UNIX UNIX SVR4 UTS Verbal Virtual Router Redundancy Protocol Vocab Vocabulary VRRP Web Services WiMAX Windows wired.com Wireless Sensor Network Words WSN