PERTEMUAN VII Multithreaded Programming

TUJUAN PRAKTIKUM

Praktikan mampu membuat program sederhana mengenai threading

7.1 Pengertian Multithreading dan Thread Multithreading adalah suatu kemampuan yang memungkinkan beberapa kumpulan instruksi atau proses dapat dijalankan secara bersamaan dalam sebuah program. Satu kumpulan instruksi yang akan dieksekusi secara independen dinamakan thread. Thread sangat berguna untuk membuat proses yang interaktif; misalnya pada permainan (game). Dengan menggunakan sejumlah thread, program tetap dapat menggerakkan sejumlah objek sembari memberikan kesempatan pemakai untuk melakukan tanggapan melalui keyboard. Web browser merupakan contoh lain penggunaan thread. Tanpa thread, Web browser akan menghentikan segala tanggapan terhadap pemakai ketika perangkat lunak tersebut sedang mengambil isi dari suatu URL.

7.2 Pembuatan Thread Thread pada Java ditangani melalui dua mekanisme. Cara pertama dilakukan dengan memperluas kelas Thread, sedangkan cara kedua dilakukan dengan mengimplementasikan Runnable.

7.2.1 Thread dengan Menggunakan kelas Thread Cara pertama untuk membuat thread adalah dengan memperluas kelas Thread dan kemudian menuliskan kembali kode pada metode run(). Secara prinsip, hal ini dilakukan dengan bentuk semacam berikut: class namaKelas extends Thread { public void run() { ... }

Lab. Teknik Informatika - FTI Universitas Gunadarma

88

} Contoh1 : // nama file : UjiThread.java public class UjiThread { public static void main (String [] args) { Mobil m1 = new Mobil(“M-1”); Mobil m2 = new Mobil(“M-2”); m1.start(); m2.start(); } } class Mobil extends Thread { // konstruktor public Mobil (String id) { super (id); } // Mendefinisikan sendiri run() public void run() { String nama = getName(); for (int i=0; i<5; i++) { try { sleep(1000); // Tunggu 1 detik } catch(InterruptedException ie) { System.out.println(”Terinterupsi”); } System.out.println(”Thread ” + nama + ”:Posisi” + i ); } } } Pembahasan contoh1: public class UjiThread { public static void main (String [] args) { Mobil m1 = new Mobil(“M-1”); Mobil m2 = new Mobil(“M-2”); m1.start(); m2.start(); } } Pada metode main(), yang menjadi titik awal pengeksekusian program, dua buah objek berkelas Mobil diciptakan dan dirujuk oleh m1 dan m2 secara berturutan. Pernyataan m1.start(); yang terletak sesudah penciptaan kedua objek berkelas Mobil digunakan untuk menjalankan metode run()yang terdapat pada kelas Mobil untuk objek yang dirujuk oleh

Lab. Teknik Informatika - FTI Universitas Gunadarma

89

m1. Serupa dengan hal itu. m2.start(); Akan membuat run() pada kelas Mobil untuk objek yang dirujuk oleh m2 dijalankan. Pendefinisian kelas Mobil dilakukan dengan membuatnya sebagai subkelas dari kelas Thread. Seperti sintaks berikut: class Mobil extends Thread { kelas Mobil menyebutkan extends Thread. Didalam pendefinisian kelas Mobil terdapat pendefinisian konstruktor Mobil dan metode run(). Konstruktor didefinisikan sebagai berikut: public Mobil (String id) { super (id); } Konstruktor mengandung sebuah parameter yang mewakili nama untuk thread. Parameter ini dilewatkann ke superkelas dengan memanggil super(id); Metode run() menyatakan tindakan yang akan dilakukan oleh thread. Pada contoh ini, mula-mula nama thread diambil melalui pemanggilan metode getName() dan kemudian diberikan ke variabel bernama nama yang bertipe String. Selanjutnya, pernyataan for digunakan untuk menuliskan informasi sebanyak 5 buah baris yang mengandung nama thread dan posisinya. Namun, sebelum informasi ditulis, pernyataan tersebut akan membuat thread tertidur selama 1 detik melalui pernyataan: try { sleep(1000); // Tunggu 1 detik } catch(InterruptedException ie) { System.out.println(”Terinterupsi”); } Tujuannya adalah memberi kesempatan yang lebih besar terhadap thread lain untuk diproses. Pada pernyataan diatas, try…catch digunakan untuk menangkap eksepsi kalau terjadi suatu interupsi ketika thread tertidur. Ketika sebuah thread tertidur, ia benar-benar tidak melakukan kegiatan apapun. Jadi pada saat itu thread tersebut tidak menggunakan CPU sama sekali. sleep() adalah metode pada kelas Thread (dan tentu saja diwariskan ke subkelas) yang berfungsi untuk membuat thread tertidur. Argumennya berupa nilai dalam satuan milidetik(1 detik sama dengan 1000milidetik). Output contoh 1: Thread M-1:Posisi0 Thread M-2:Posisi0 Thread M-1:Posisi1 Thread M-2:Posisi1 Thread M-1:Posisi2 Thread M-2:Posisi2 Thread M-1:Posisi3 Thread M-2:Posisi3 Thread M-1:Posisi4 Thread M-2:Posisi4

Lab. Teknik Informatika - FTI Universitas Gunadarma

90

Hasil diatas menunjukkan bahwa proses untuk thread dengan nama M-1 dan M-2 dilakukan secara bergantian 7.2.2 Thread Melalui Runnable Runnable sesungguhnya adalah sebuah interface. Dengan mengimplementasikan interface ini, sebuah kelas yang menangani thread dapat diciptakan. Contoh tentang hal ini dapat dilihat pada UjiThread2.java. Kelas Thread merupakan implementasi dari Runnable. Contoh2: // nama file : UjiThread2.java public class UjiThread2 { public static void main (String [] args) { Thread m1 = new Thread(new Mobil("M-1")); Thread m2 = new Thread(new Mobil("M-2")); m1.start(); m2.start(); } } class Mobil implements Runnable { String nama; // konstruktor public Mobil (String id) { nama = id; } public void run() { for (int i=0; i<5; i++) { try { Thread.currentThread().sleep(1000); } catch(InterruptedException ie) { System.out.println("Terinterupsi"); } System.out.println("Thread " + nama + ":Posisi" + i ); } } } Pembahasan contoh2: Program diatas hampir sama dengan program UjiThread.java. Beberapa perbedaan yang perlu dibahas: • Pembuatan objek thread dilakukan melalui: Thread m1 = new Thread(new Mobil("M-1")); Thread m2 = new Thread(new Mobil("M-2")); Perhatikan bahwa m1 dan m2 merupakan variable yang merujuk objek berkelas

Lab. Teknik Informatika - FTI Universitas Gunadarma

91

• • • •

Thread. Pembentukan objek dilakukan dengan menggunakan kelas Thread dengan argument berupa objek berkelas Mobil. Kelas Mobil didefinisikan dengan mengimplementasikan interface Runnable seperti terlihat pada baris berikut: class Mobil implements Runnable { Di dalam kelas Mobil dideklarasikan variabel instan bernama nama, yang digunakan untuk menyimpan nama thread. Di dalam konstruktor Mobil, variabel instan bernama nama tersebut diisi dengan nilai agumen. Di dalam metode run(), mengingat sleep() adalah metode milik kelas Thread, pemanggilannya harus dilakukan dengan memlibatkan kelas tersebut. Seperti sintaks berikut: Thread.currentThread().sleep(1000); Dalam hal ini currentThread() adalah metode pada kelas Thread yang digunakan untuk memperoleh thread sekarang.

Output contoh2: Thread M-1:Posisi0 Thread M-2:Posisi0 Thread M-1:Posisi1 Thread M-2:Posisi1 Thread M-1:Posisi2 Thread M-2:Posisi2 Thread M-1:Posisi3 Thread M-2:Posisi3 Thread M-1:Posisi4 Thread M-2:Posisi4 7.3 Daur Hidup Thread Keberadaan sebuah thread dimulai tepat ketika thread tersebut diciptakan. Sebuah thread dieksekusi sampai salah satu kondisi berikut terjadi: 1. Eksekusi terhadap run() berakhir, 2. Terinterupsi oleh eksepsi yang tidak tertangkap, 3. Metode stop() dipanggil. Metode stop() tidak dianjurkan untuk digunakan dalam thread karena tidak aman. Untuk mengetahui suatu thread masih hidup atau sudah mati, metode bernama isAlive() pada kelas Thread bisa digunakan. Metode ini memberikan nilai balik berupa true kalau thread masih hidup dan false kalau sudah mati. Contoh3: // nama file : UjiThread3.java public class UjiThread3 { public static void main (String [] args) { Mobil m1 = new Mobil("M-1"); Mobil m2 = new Mobil("M-2"); m1.start(); m2.start();

Lab. Teknik Informatika - FTI Universitas Gunadarma

92

// beri komentar ketika thread berakhir boolean m1Berakhir=false; boolean m2Berakhir=false; do { // cek keberadaan thread m1 if (!m1Berakhir && !m1.isAlive()){ m1Berakhir=true; System.out.println("Thread m1 berakhir"); } // cek keberadaan thread m2 if (!m2Berakhir && !m2.isAlive()){ m2Berakhir=true; System.out.println("Thread m2 berakhir"); } } while (!m1Berakhir || !m2Berakhir); } } class Mobil extends Thread { // konstruktor public Mobil (String id) { super (id); } // Mendefinisikan sendiri run() public void run() { String nama = getName(); for (int i=0; i<5; i++) { try { sleep(1000); // Tunggu 1 detik } catch(InterruptedException ie) { System.out.println("Terinterupsi"); } System.out.println("Thread " + nama + ":Posisi" + i ); } } } Pembahasan contoh3: Program diatas adalah hasil modifikasi terhadap program UjiThread2.java. Yang dicetak tebal adalah bagian yang diubah dan ditambah. Pengujian kedua thread masih hidup atau sudah mati dilakukan melalui pernyataan do…while. Sebelum pernyataan ini dijalankan, dilakukan pendeklarasian dua buah variable bertipe Boolean sebagai berikut: boolean m1Berakhir=false; boolean m2Berakhir=false;

Lab. Teknik Informatika - FTI Universitas Gunadarma

93

Masing-masing diberi nilai awal berupa false yang menyatakan bahwa objek yang dirujuk oleh m1 dan m2 belum berakhir. Pengujian objek yang dirujuk m1 sudah berakhir atau belum dilakukan melalui pernyataan: if (!m1Berakhir && !m1.isAlive()){ m1Berakhir=true; System.out.println("Thread m1 berakhir"); } Jika m1Berakhir bernilai false dan m1.isAlive() menghasilkan nilai false (yang berarti thread sudah mati) maka variabel m1Berakhir diisi dengan nilai true dan tulisan berikut ditampilkan: Thread m1 berakhir Pengujian m2 dilakukan dengan cara yang sama. Output contoh3: Thread M-1:Posisi0 Thread M-2:Posisi0 Thread M-1:Posisi1 Thread M-2:Posisi1 Thread M-1:Posisi2 Thread M-2:Posisi2 Thread M-1:Posisi3 Thread M-2:Posisi3 Thread M-1:Posisi4 Thread m1 berakhir Thread M-2:Posisi4 Thread m2 berakhir 7.4 Sinkronisasi Sinkronisasi merupakan suatu upaya agar kode tertentu dijalankan secara berurutan dengan jaminan kode tersebut tidaka akan dijalankan oleh yang lain dalam waktu bersamaan. Jika sinkronisasi diterapkan dalam metode, dipastikan bahwa seluruh kode di dalam metode tersebut dijalankan tanpa diinterupsi oleh yang lain. Contoh: // nama file : TesSinkron.java public class TesSinkron { public static void main (String [] args) { Mobil m1 = new Mobil("M-1"); Mobil m2 = new Mobil("M-2"); m1.start(); m2.start(); } }

Lab. Teknik Informatika - FTI Universitas Gunadarma

94

class Mobil extends Thread { // konstruktor public Mobil (String id) { super (id); } // Mendefinisikan sendiri run() public void run() { String nama = getName(); SinkronisasiKeluaran.info(nama); } } class SinkronisasiKeluaran { public static synchronized void info(String nama){ for (int i=0; i<5; i++) { try { Thread.sleep(1000); } catch(InterruptedException ie) { System.out.println("Terinterupsi"); } System.out.println("Thread " + nama + ":Posisi" + i ); } } } Output: Thread M-1:Posisi0 Thread M-1:Posisi1 Thread M-1:Posisi2 Thread M-1:Posisi3 Thread M-1:Posisi4 Thread M-2:Posisi0 Thread M-2:Posisi1 Thread M-2:Posisi2 Thread M-2:Posisi3 Thread M-2:Posisi4 Dengan menambahkan synchronized pada metode info() pada kelas SinkronisasiKeluaran terlihat bahwa seluruh kode pada metode tersebut akan dijalankan sekiranya dipanggil oleh sebuah thread. Tampak bahwa thread bernama M-1 dijalankan secara tuntas dan kemudian thread bernama M2 dijalankan sampai berakhir. Jadi tidak terjadi pengeksekusian secara bersamaan. 7.5 Prioritas Thread Setiap thread dalam Java memiliki prioritas. Defaultnya, suatu thread menurunkan prioritas dari thread induknya atau dapat menaikkan/menurunkan prioritas setiap thread.

Lab. Teknik Informatika - FTI Universitas Gunadarma

95

Kelas Thread menyediakan metode setPriority() dengan argument berupa angka yang menyatakan prioritas antara MIN_PRIORITY(didefinisikan sebagai 1 dalam kelas Thread) dan MAX_PRIORITY ( didefinisikan sebagai 10). NORM_PRIORITY didefinisikan sebagai 5. Contoh: // nama file : UjiPrioritas.java public class UjiPrioritas { public static void main (String [] args) { Mobil m1 = new Mobil("M-1"); Mobil m2 = new Mobil("M-2"); m2.setPriority(8); m1.start(); m2.start(); } } class Mobil extends Thread { // konstruktor public Mobil (String id) { super (id); } // Mendefinisikan sendiri run() public void run() { String nama = getName(); for (int i=0; i<5; i++) { System.out.println("Thread " + nama + ":Posisi " + i ); } } } m2.setPriority(8); // digunakan untuk mengatur prioritas m2 agar lebih tinggi daripada m1. Output: Thread M-2:Posisi 0 Thread M-2:Posisi 1 Thread M-2:Posisi 2 Thread M-2:Posisi 3 Thread M-2:Posisi 4 Thread M-1:Posisi 0 Thread M-1:Posisi 1 Thread M-1:Posisi 2 Thread M-1:Posisi 3 Thread M-1:Posisi 4

Lab. Teknik Informatika - FTI Universitas Gunadarma

96

STEP BY STEP 1. Jelaskan tentang multithreading! 2. Bagaimana cara membuat thread?

MATERI PRAKTIKUM 1. Memberikan penjelasan tentang multithreading 2. Memberikan penjelasan serta memberikan contoh pembuatan thread.

LAPORAN AKHIR Buatlah kesimpulan mengenai multithreading pada bahasa pemrograman JAVA yang telah dipraktekkan beserta dengan program-program yang telah dibuat berikut tampilan hasilnya.

Lab. Teknik Informatika - FTI Universitas Gunadarma

97