Program ini meng-
import package
java.util untuk mengambil
Date yang akan kita gunakan sebagai data yang
dipertukarkan proses konsumen dan produsen melalui
buffer
(baris 006).
Contoh 25.2 MasalahProdusenKonsumen
008 public class MasalahProdusenKonsumen
009 {
010 public static void main(String args[])
011 {
012 BoundedBuffer server = new BoundedBuffer();
013 Produsen threadProdusen = new Produsen(server);
014 Konsumen threadKonsumen = new Konsumen(server);
015 threadProdusen.start();
016 threadKonsumen.start();
017 }
018 }
Kelas
MasalahProdusenKonsumen mengandung
method
main yang membuat instansiasi objek
BoundedBuffer yang diberi nama
server.
Server merupakan antrian sementara yang akan
digunakan oleh produsen dan konsumen untuk menaruh data yang
dipertukarkan.
Contoh 25.3 BoundedBuffer
029 public BoundedBuffer()
030 {
031 count=tmptMsk=tmptKlr=0;
032 buffer=new Object[UK_BUFFER];
033 mutex=new Semaphore(1);
034 tempat_kosong=new Semaphore(UK_BUFFER);
035 tempat_terisi=new Semaphore(0);
036 }
Selain itu
MasalahProdusenKonsumen akan membuat
instansiasi dari kelas
Produsen dan
Konsumen, yang masing-masing berjalan
sebagai
thread yang paralel dengan
main. Ketika
thread produsen dan konsumen
dimulai di
main dengan dipanggilnya fungsi
start()(baris 015 dan 016), masing-masing
proses itu akan menjalankan
method
run()-nya seperti di bawah ini.
Contoh 25.4 Method Run Konsumen
072 public void run()
073 {
074 Date data;
075 while(true)
076 {
077 BoundedBuffer.napping();
078 System.out.println("Konsumen ingin mengambil.");
079 data = (Date) buffer.ambil();
080 }
081 }
Contoh 25.5 Method Run Produsen
091 public void run()
092 {
093 Date data;
094 while(true)
095 {
096 data=new Date();
097 BoundedBuffer.napping();
098 System.out.println("Produsen menghasilkan : "+data);
099 System.out.println("Produsen ingin menaruh.");
100 buffer.taruh(data);
101 }
102 }
Dapat dilihat bahwa masing-masing
thread akan tidur sejenak dengan
fungsi
napping()(baris 077 dan baris 097), untuk
memberi jeda antar proses. Waktu untuk tidur ini adalah angka
random yang dihasilkan dari
Math.random()(baris 039).
Contoh 25.6 Napping
037 public static void napping()
038 {
039 int tidur = (int) (TIDUR*Math.random());
040 try{ Thread.sleep(tidur*1000);}
041 catch(InterruptedException e){}
042 }
Dalam fungsi
napping(), program akan menangkap jika ada
InterruptedException(baris 040-041). Perlu
diingat bahwa program ini tidak akan terminasi sendiri (akan
terjadi
loop yang terus-menerus). Dengan
demikan, kita harus menterminasi program ini dengan paksa (dengan
perintah CTRL+C), akan ditangkap di bagian
catch ini, sehingga program akan
diterminasi.
Fungsi lain yang dipanggil pada saat
thread produsen dan konsumen
menjalankan
run() adalah
taruh yang dipanggil oleh produsen dan
ambil yang dipanggil oleh konsumen.
taruh berfungsi untuk memasukkan data ke
dalam
buffer sedangkan
ambil untuk mengambil data.
Contoh 25.7 Taruh dan Ambil
043 public void taruh(Object item)
044 {
045 tempat_kosong.acquire(); mutex.acquire();
046 ++count;
047 buffer[tmptMsk]=item;
048 tmptMsk=(tmptMsk+1)% UK_BUFFER;
049 System.out.println("Produsen memasukkan : "+item);
050 mutex.release(); tempat_terisi.release();
051 }
052 public Object ambil()
053 {
054 Object item;
055 tempat_terisi.acquire(); mutex.acquire();
056 --count;
057 item=buffer[tmptKlr];
058 tmptKlr=(tmptKlr+1)%UK_BUFFER;
059 System.out.println("Konsumen mengambil : "+item);
060 mutex.release(); tempat_kosong.release();
061 return item;
062 }
Pada kelas
BoundedBuffer tadi, telah diinstansiasikan 3
buah semafor yang diinisialisasi dengan nilai 1 untuk
mutex, ukuran buffer untuk
tempat_kosong, dan 0 untuk
tempat_terisi. Semafor ini
digunakan pada saat percobaan memasukkan atau mengambil data dari
buffer oleh
thread produsen dan
konsumen.
Contoh 25.8 Instansiasi dan Inisialisasi Semafor
024 private Semaphore mutex;
025 private Semaphore tempat_kosong;
026 private Semaphore tempat_terisi;
.
.
.
033 mutex=new Semaphore(1);
034 tempat_kosong=new Semaphore(UK_BUFFER);
035 tempat_terisi=new Semaphore(0);
Dengan demikian, pada saat produsen memanggil
taruh, hal pertama yang dilakukan adalah
percobaan mengurangi jumlah tempat kosong melalui
acquire semafor tempat_kosong
(baris 045). Hal ini diikuti oleh percobaan pengambilalihan
mutex. (baris 045). Sedangkan
konsumen mencoba mengurangi jumlah tempat terisi melalui
pengambilalihan semafor tempat_terisi (baris 055). Setelah itu
konsumen berusaha mengambil alih juga semafor
mutex(baris 055). Setelah produsen
berhasil memperoleh
mutex dan mengurangi tempat_kosong,
maka ia akan mengeksekusikan baris 046-049 dari program
taruh yang merupakan
critical section. Ketika selesai,
ia akan melepas kembali
mutex dan mengupdate jumlah tempat
terisi dengan cara melepas semafor tempat_terisi. Demikian pula
dengan konsumen, setelah memperoleh semafor mutex dan
tempat_terisi, akan mengeksekusi baris 056-059 dari program
ambil(yang juga merupakan
critical section), lalu melepas
kembali mutex dan mengupdate jumlah tempat kosong dengan melepas
semafor tempat_kosong.
Contoh 25.9 Acquire Semafor
111 public synchronized void acquire()
112 {
113 while(value==0)
114 {
115 try{wait();}
116 catch(InterruptedException e){}
117 }
118 value--;
119 }
Contoh 25.10 Release Semafor
120 public synchronized void release()
121 {
122 ++value;
123 notify();
124 }
Semafor
mutex bernilai 1 untuk menandai
bahwa
buffer sedang dipakai oleh sebuah
proses. Ketika diinisialisasi pun ia bernilai 1, yang artinya di
keadaan awal
buffer tidak dipakai oleh proses
manapun. Ketika sebuah proses berusaha meng-
acquire semafor ini, dan menemui
bahwa keadaannya sedang bernilai 0 (baris 113) yang berarti
buffer sedang dipakai proses lain,
maka ia akan menunggu (baris 115) dengan fungsi
wait() sampai nilai
mutex bernilai 1 (
buffer bebas). Ketika sebuah proses
selesai, ia akan me-
release
mutex dengan menjadikan nilainya
kembali ke 1. (baris 122) dan memberitahu proses lain yang sedang
menunggu dengan memanggil
notify()(baris 123).
Semafor tempat_kosong adalah jumlah tempat kosong. Dengan demikian ketika di- acquire oleh produsen, jika bernilai 0 ( buffer penuh), maka produsen akan menunggu (baris 115), karena jika penuh maka produsen tidak bisa menimpa data yang tersimpan. Jika tidak 0, maka produsen akan mengurangi nilainya (mengurangi jumlah tempat yang kosong). Setelah produsen selesai maka ia akan mengubah nilai tempat_terisi (menambahkan 1 tempat yang terisi) dengan me- release semafor tempat_terisi. Untuk konsumen sama saja, namun yang di- acquire adalah tempat_terisi (jika tempat_terisi=0 berarti buffer kosong, belum ada yang terisi) dan yang di- release ketika proses selesai adalah tempat_kosong.
Dengan demikian, produsen dan konsumen akan secara bergantian menaruh atau mengambil data dari buffer, dan produsen tidak akan menaruh data jika buffer penuh (tidak akan menimpa data yang sudah ada), dan konsumen tidak bisa pula mengambil data jika buffer kosong.
Salah satu contoh keluaran program ini adalah:
Contoh 25.11 Contoh keluaran
Konsumen ingin mengambil.
Produsen menghasilkan : Tue Apr 10 16:12:16 ICT 2007
Produsen ingin menaruh.
Produsen memasukkan : Tue Apr 10 16:12:16 ICT 2007
Konsumen mengambil : Tue Apr 10 16:12:16 ICT 2007
Produsen menghasilkan : Tue Apr 10 16:12:19 ICT 2007
Produsen ingin menaruh.
Produsen memasukkan : Tue Apr 10 16:12:19 ICT 2007
Konsumen ingin mengambil.
Konsumen mengambil : Tue Apr 10 16:12:19 ICT 2007
Produsen menghasilkan : Tue Apr 10 16:12:20 ICT 2007
Konsumen ingin mengambil.
Produsen ingin menaruh.
Produsen memasukkan : Tue Apr 10 16:12:20 ICT 2007
Konsumen mengambil : Tue Apr 10 16:12:20 ICT 2007
Konsumen ingin mengambil.
Produsen menghasilkan : Tue Apr 10 16:12:22 ICT 2007
Produsen ingin menaruh.
Produsen memasukkan : Tue Apr 10 16:12:22 ICT 2007
Konsumen mengambil : Tue Apr 10 16:12:22 ICT 2007