Monday, December 26, 2016

Bab 11. Soal & Penyelesaian Java


11
Pemrograman Multithreaded






Program multithreaded memuat dua atau lebih bagian program yang dapat berjalan bersamaan. Setiap bagian program tersebut dinamakan dengan thread, dan setiap thread mendefinisikan jalur eksekusi sendiri. Jadi, multithreading merupakan salah satu bentuk dari multitasking.

Kelas Thread mendefinisikan beberapa metode untuk mengelola thread, yaitu:

Metode
Penjelasan
getName
Mendapatkan nama thread.
getPriority
Mendapatkan prioritas thread.
isAlive
Menentukan jika sebuah thread masih berjalan.
join
Menunggu untuk sebuah thread berhenti.
run
Titik entri untuk thread.
sleep
Menunda sebuah thread untuk periode waktu tertentu.
start
Memulai sebuah thread dengan memanggil metode run.

Soal dan Penyelesaian
1.       Tulislah sebuah program sederhana untuk menciptakan thread baru dan menjalankannya.

Penyelesaian

// Menciptakan sebuah thread kedua.
class ThreadBaru implements Runnable {
    Thread t;

    ThreadBaru() {
        // Menciptakan sebuah thread baru
        t = new Thread(this, "Demo Thread");
        System.out.println("Thread anak: " + t);
        t.start(); // memulai thread
    }

    // Ini merupakan titik entri untuk thread kedua.
    public void run() {
        try {
            for(int i = 5; i > 0; i--) {
                System.out.println("Thread anak: " + i);
                Thread.sleep(500);
            }
        }
        catch (InterruptedException e) {
            System.out.println("Anak diinterupsi.");
        }
        System.out.println("Keluar dari thread anak.");
    }
}

public class DemoThread {
    public static void main(String args[]) {
        new ThreadBaru(); // menciptakan sebuah thread baru
       
        try {
            for(int i = 5; i > 0; i--) {
                System.out.println("Thread main: " + i);
                Thread.sleep(1000);
            }
        }
        catch (InterruptedException e) {
            System.out.println("Thread main diinterupsi.");
        }
        System.out.println("Keluar dari thread main.");
    }
}

Keluaran Program

Thread anak: Thread[Demo Thread,5,main]
Thread main: 5
Thread anak: 5
Thread anak: 4
Thread main: 4
Thread anak: 3
Thread anak: 2
Thread main: 3
Thread anak: 1
Keluar dari thread anak.
Thread main: 2
Thread main: 1
Keluar dari thread main.

Pelewatan this sebagai argumen pertama mengindikasikan bahwa Anda ingin thread baru untuk memanggil metode run pada objek this. Selanjutnya, start dipanggil, yang memulai thread. Ini menyebabkan loop for pada thread anak dimulai. Setelah memanggil start, konstruktor ThreadBaru kembali ke main. Ketika thread main dimulai, ia memasuki loop for. Kedua thread sekarang berjalan bersamaan, berbagi CPU, sampai kedua loop selesai.

2.       Cara kedua dalam menciptakan sebuah thread adalah dengan menciptakan kelas baru yang mewarisi Thread, dan kemudian menciptakan sebuah instans dari kelas tersebut. Kelas pewaris harus mendefinisikan-ulang metode run, yang merupakan titik entri bagi thread baru. Kelas tersebut juga harus memanggil start untuk memulai eksekusi atas thread baru. Tulislah sebuah program untuk mengilustrasikan situasi ini.

Penyelesaian

// Menciptakan thread kedua dengan mewarisi dari kelas Thread
class ThreadBaru extends Thread {
    ThreadBaru() {
        // Menciptakan thread baru
        super("Demo Thread");
        System.out.println("Thread anak: " + this);
        start(); // memulai thread
    }

    // Ini adalah titik entri untuk thread kedua.
    public void run() {
        try {
            for(int i = 5; i > 0; i--) {
                System.out.println("Thread anak: " + i);
                Thread.sleep(500);
            }
        }
        catch (InterruptedException e) {
            System.out.println("Thread anak diinterupsi.");
        }
        System.out.println("Keluar dari thread anak.");
    }
}

public class PewarisanThread {
    public static void main(String args[]) {
        new ThreadBaru(); // menciptakan sebuah thread baru

        try {
            for(int i = 5; i > 0; i--) {
                System.out.println("Thread main: " + i);
                Thread.sleep(1000);
            }
        }
        catch (InterruptedException e) {
            System.out.println("Thread main diinterupsi.");
        }
        System.out.println("Keluar dari thread main.");
    }
}

Keluaran Program

Thread anak: Thread[Demo Thread,5,main]
Thread main: 5
Thread anak: 5
Thread anak: 4
Thread main: 4
Thread anak: 3
Thread anak: 2
Thread main: 3
Thread anak: 1
Keluar dari thread anak.
Thread main: 2
Thread main: 1
Keluar dari thread main.

3.       Sejauh ini, Anda menggunakan dua thread: thread main dan satu thread anak. Namun, program Anda dapat memiliki sebanyak mungkin thread yang Anda inginkan. Tulislah sebuah program untuk mengilustrasikan situasi ini.

Penyelesaian

// Menciptakan thread jamak.
class ThreadBaru implements Runnable {
    String nama; // name of thread
    Thread t;

    ThreadBaru(String namaThread) {
        nama = namaThread;
        t = new Thread(this, nama);
        System.out.println("Thread baru: " + t);
        t.start(); // memulai thread
    }

    // Ini merupakan titik entri untuk thread.
    public void run() {
        try {
            for(int i = 5; i > 0; i--) {
                System.out.println(nama + ": " + i);
                Thread.sleep(1000);
            }
        }
        catch (InterruptedException e) {
            System.out.println(nama + " diinterupsi");
        }
        System.out.println(nama + " keluar.");
    }
}

public class DemoThreadJamak {
    public static void main(String args[]) {
        new ThreadBaru("Satu"); // memulai tiga thread
        new ThreadBaru("Dua");
        new ThreadBaru("Tiga");

        try {
            // menunggu untuk thread lain berakhir
            Thread.sleep(10000);
        }
        catch (InterruptedException e) {
            System.out.println("Thread main diinterupsi");
        }
        System.out.println("Keluar dari thread main.");
    }
}

Keluaran Program

Thread baru: Thread[Satu,5,main]
Thread baru: Thread[Dua,5,main]
Thread baru: Thread[Tiga,5,main]
Satu: 5
Dua: 5
Tiga: 5
Tiga: 4
Dua: 4
Satu: 4
Tiga: 3
Dua: 3
Satu: 3
Tiga: 2
Satu: 2
Dua: 2
Satu: 1
Dua: 1
Tiga: 1
Satu keluar.
Tiga keluar.
Dua keluar.
Keluar dari thread main.

4.       Tulis-ulanglah kode pada soal no 3, dengan menggunakan metode join untuk memastikan bahwa thread main merupakan thread terakhir yang berhenti. Program yang ditulis juga mendemonstrasikan metode isAlive.

Penyelesaian

// Menggunakan metode join() untuk menunggu thread selesai.
class ThreadBaru implements Runnable {
    String nama; // nama thread
    Thread t;

    ThreadBaru(String namaThread) {
        nama = namaThread;
        t = new Thread(this, nama);
        System.out.println("Thread baru: " + t);
        t.start(); // memulai thread
    }

    // Ini merupakan titik entri untuk thread.
    public void run() {
        try {
            for(int i = 5; i > 0; i--) {
                System.out.println(nama + ": " + i);
                Thread.sleep(1000);
            }
        }
        catch (InterruptedException e) {
            System.out.println(nama + " diinterupsi.");
        }
        System.out.println(nama + " keluar.");
    }
}

public class DemoJoin {
    public static void main(String args[]) {
        ThreadBaru ob1 = new ThreadBaru("Satu");
        ThreadBaru ob2 = new ThreadBaru("Dua");
        ThreadBaru ob3 = new ThreadBaru("Tiga");

        System.out.println("Thread Satu berjalan: "
            + ob1.t.isAlive());
        System.out.println("Thread Dua berjalan: "
            + ob2.t.isAlive());
        System.out.println("Thread Tiga berjalan: "
            + ob3.t.isAlive());

        // menunggu thread-thread tersebut selesai
        try {
            System.out.println("Menunggu untuk thread-thread selesai.");
            ob1.t.join();
            ob2.t.join();
            ob3.t.join();
        }
        catch (InterruptedException e) {
            System.out.println("Thread main diinterupsi");
        }

        System.out.println("Thread Satu berjalan: "
            + ob1.t.isAlive());
        System.out.println("Thread Dua berjalan: "
            + ob2.t.isAlive());
        System.out.println("Thread Tiga berjalan: "
            + ob3.t.isAlive());
       
        System.out.println("Thread main keluar.");
    }
}

Keluaran Program

Thread baru: Thread[Satu,5,main]
Thread baru: Thread[Dua,5,main]
Thread baru: Thread[Tiga,5,main]
Satu: 5
Thread Satu berjalan: true
Thread Dua berjalan: true
Thread Tiga berjalan: true
Dua: 5
Menunggu untuk thread-thread selesai.
Tiga: 5
Satu: 4
Dua: 4
Tiga: 4
Tiga: 3
Satu: 3
Dua: 3
Tiga: 2
Satu: 2
Dua: 2
Dua: 1
Satu: 1
Tiga: 1
Dua keluar.
Satu keluar.
Tiga keluar.
Thread Satu berjalan: false
Thread Dua berjalan: false
Thread Tiga berjalan: false
Thread main keluar.

5.       Prioritas thread dipakai untuk memutuskan kapan setiap thread diijinkan untuk berjalan. Anda dapat menetapkan prioritas sebuah thread menggunakan metode setPriority. Tulislah sebuah program untuk mendemonstrasikan dua thread dengan dua prioritas yang berbeda. Satu thread ditetapkan dua level di atas prioritas normal, yang didefinisikan oleh Thread.NORM_PRIORITY, dan thread lain ditetapkan dua level di bawahnya. Kedua thread dijalankan selamat sepuluh detik. Setiap thread mengeksekusi sebuah loop, menghitung jumlah iterasi. Setelah sepuluh detik, thread main menghentikan kedua thread tersebut. Jumlah iterasi dari kedua thread kemudian ditampilkan.

Penyelesaian

// Mendemonstrasikan prioritas thread.
class Pewaktu implements Runnable {
    long waktu = 0;
    Thread t;
    private volatile boolean berjalan = true;

    public Pewaktu(int p) {
        t = new Thread(this);
        t.setPriority(p);
    }

    public void run() {
        while (berjalan) {
            waktu++;
        }
    }

    public void stop() {
        berjalan = false;
    }

    public void start() {
        t.start();
    }
}

public class DemoPrioritasThread {
    public static void main(String args[]) {
        Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
        Pewaktu tinggi = new Pewaktu(Thread.NORM_PRIORITY + 2);
        Pewaktu rendah = new Pewaktu(Thread.NORM_PRIORITY - 2);

        rendah.start();
        tinggi.start();

        try {
            Thread.sleep(10000);
        }
        catch (InterruptedException e) {
            System.out.println("Thread main diinterupsi.");
        }

        rendah.stop();
        tinggi.stop();

        // Menunggu thread-thread anak berhenti.
        try {
            tinggi.t.join();
            rendah.t.join();
        }
        catch (InterruptedException e) {
            System.out.println("InterruptedException ditangkap");
        }

        System.out.println("Thread prioritas-rendah: " + rendah.waktu);
        System.out.println("Thread prioritas-tingi: " + tinggi.waktu);
    }
}

Keluaran Program

Thread prioritas-rendah: 3655610649
Thread prioritas-tingi: 3673799854

6.       Ketika dua atau lebih thread memerlukan akses terhadap sumberdaya yang sama, maka diperlukan sebuah cara untuk memastikan bahwa sumberdaya akan digunakan oleh satu thread pada suatu waktu. Proses ini dikenal dengan sinkronisasi.

Untuk memahami kebutuhan akan sinkronisasi, tulislah sebuah program untuk mengilustrasikannya. Program tersebut memiliki tiga kelas sederhana. Kelas pertama, Panggilsaya, yang memiliki satu metode bernama panggil. Metode panggil memerlukan sebuah parameter String yang bernama psn. Metode ini mencoba untuk menampilkan string psn di dalam kurung siku. Hal menarik untuk diperhatikan adalah bahwa setelah panggil menampilkan kurung siku pembuka dan string psn, ia memanggil Thread.sleep(1000), yang menunda thread tersebut selama satu detik.

Konstruktor dari kelas berikutnya, Pemanggil, memerlukan sebuah referensi yang menunjuk ke suatu instans dari kelas Panggilsaya dan sebuah String, yang disimpan di dalam target dan psn. Konstruktor tersebut juga menciptakan sebuah thread baru yang akan memanggil metode run dari objek tersebut. Thread itu dimulai. Metode run untuk Pemanggil memanggil metode panggil pada instans target dari Panggilsaya, melewatkan string psn. Terakhir, kelas Sinkron dimulai dengan menciptakan sebuah instans dari Panggilsaya, dan tiga instans dari Pemanggil, masing-masing dengan string pesan unik. Instans sama dari Panggilsaya dilewatkan kepada tiap Pemanggil.

Penyelesaian

// Program ini tidak disinkronisasi.
class Panggilsaya {
    void panggil(String msg) {
        System.out.print("[" + msg);
        try {
            Thread.sleep(1000);
        }
        catch(InterruptedException e) {
            System.out.println("Diinterupsi");
        }
        System.out.println("]");
    }
}

class Pemanggil implements Runnable {
    String psn;
    Panggilsaya target;
    Thread t;

    public Pemanggil(Panggilsaya targ, String s) {
        target = targ;
        psn = s;
        t = new Thread(this);
        t.start();
    }

    public void run() {
        target.panggil(psn);
    }
}

public class DemoSinkronisasiThread {
    public static void main(String args[]) {
        Panggilsaya target = new Panggilsaya();
        Pemanggil ob1 = new Pemanggil(target, "Dunia");
        Pemanggil ob2 = new Pemanggil(target, "Sinkronisasi");
        Pemanggil ob3 = new Pemanggil(target, "Thread");

        // Tunggu thread-thread berhenti
        try {
            ob1.t.join();
            ob2.t.join();
            ob3.t.join();
        }
        catch(InterruptedException e) {
            System.out.println("Diinterupsi");
        }
    }
}

Keluaran Program

[Dunia[Sinkronisasi[Thread]
]
]

7.       Tulis-ulanglah kode pada soal no 6 agar menggunakan katakunci synchronized untuk mensinkronisasi thread.

Penyelesaian

// Program ini tidak disinkronisasi.
class Panggilsaya {
    void panggil(String msg) {
        System.out.print("[" + msg);
        try {
            Thread.sleep(1000);
        }
        catch(InterruptedException e) {
            System.out.println("Diinterupsi");
        }
        System.out.println("]");
    }
}

class Pemanggil implements Runnable {
    String psn;
    Panggilsaya target;
    Thread t;

    public Pemanggil(Panggilsaya targ, String s) {
        target = targ;
        psn = s;
        t = new Thread(this);
        t.start();
    }

    // sinkronisasi pemanggilan-pemanggilan terhadap panggil()
    public void run() {
        synchronized(target) { // blok tersinkronisasi
        target.panggil(psn);
        }
    }
}

public class DemoSinkronisasiThread2 {
    public static void main(String args[]) {
        Panggilsaya target = new Panggilsaya();
        Pemanggil ob1 = new Pemanggil(target, "Dunia");
        Pemanggil ob2 = new Pemanggil(target, "Sinkronisasi");
        Pemanggil ob3 = new Pemanggil(target, "Thread");

        // Tunggu thread-thread berhenti
        try {
            ob1.t.join();
            ob2.t.join();
            ob3.t.join();
        }
        catch(InterruptedException e) {
            System.out.println("Diinterupsi");
        }
    }
}

Keluaran Program

[Dunia]
[Thread]
[Sinkronisasi]

8.       Jave memuat mekanisme komunikasi antar-thread menggunakan metode wait, notify, dan notifyAll. Ketiga metode ini diimplementasikan sebagai metode final di dalam kelas Object, jadi semua kelas memilikinya. Ketiga metode hanya dapat dipanggil dari dalam konteks tersinkronisasi. Berikut penjelasan dari ketiga metode tersebut:
·         wait memberitahu thread pemanggil untuk beristrahat sampai thread lain berjalan dan memanggil notify.
·         notify membangunkan sebuah thread yang memanggil wait pada objek yang sama.
·         notifyAll membangunkan semua thread yang memanggil wait pada objek yang sama. Salah satu dari thread tersebut akan diberikan akses.

Tulislah sebuah program yang secara tidak tepat mengimplementasikan suatu permasalahan produser/konsumen. Program memuat empat kelas: Antrian, antrian yang akan disinkronisasi; Produser, objek yang menghasilkan entri-antri antrian; Konsumen, objek yang mengkonsumsi entri-entri antrian; dan DemoKomunikasiThread, kelas yang menciptakan satu Antrian, satu Produser, dan satu Konsumen.

Penyelesaian

// Implementasi komunikasi antar thread yang tidak tepat.
class Antrian {
    int n;
    synchronized int ambil() {
        System.out.println("Mengambil: " + n);
        return n;
    }

    synchronized void tempatkan(int n) {
        this.n = n;
        System.out.println("Menempatkan: " + n);
    }
}

class Produser implements Runnable {
    Antrian q;
    Produser(Antrian q) {
        this.q = q;
        new Thread(this, "Produser").start();
    }

    public void run() {
        int i = 0;
        while(true) {
            q.tempatkan(i++);
        }
    }
}

class Konsumen implements Runnable {
    Antrian q;
    Konsumen(Antrian q) {
        this.q = q;
        new Thread(this, "Konsumen").start();
    }

    public void run() {
        while(true) {
            q.ambil();
        }
    }
}

public class DemoKomunikasiThread {
    public static void main(String args[]) {
        Antrian q = new Antrian();
        new Produser(q);
        new Konsumen(q);
        System.out.println("Tekan Control-C untuk menghentikan.");
    }
}

Keluaran Program

Menempatkan: 0
Menempatkan: 1
Menempatkan: 2
Menempatkan: 3
Menempatkan: 4
Menempatkan: 5
Tekan Control-C untuk menghentikan.
Menempatkan: 6
Menempatkan: 7
Menempatkan: 8
Menempatkan: 9
Menempatkan: 10
Menempatkan: 11
Menempatkan: 12
Mengambil: 12
Mengambil: 12
Mengambil: 12
Mengambil: 12
Mengambil: 12
Mengambil: 12
Mengambil: 12
Mengambil: 12

9.       Tulis-ulanglah kode pada soal no 8 dengan menggunakan wait dan notify.

Penyelesaian

// Implementasi komunikasi antar thread yang tepat.
class Antrian {
    int n;
    boolean nilaiSet = false;
   
    synchronized int ambil() {
        while(!nilaiSet)
        try {
            wait();
        }
        catch(InterruptedException e) {
            System.out.println("InterruptedException ditangkap");
        }

        System.out.println("Mengambil: " + n);
        nilaiSet = false;
        notify();
        return n;
    }

    synchronized void tempatkan(int n) {
        while(nilaiSet)
            try {
                wait();
            }
            catch(InterruptedException e) {
                System.out.println("InterruptedException ditangkap");
            }
            this.n = n;
            nilaiSet = true;
            System.out.println("Menempatkan: " + n);
            notify();
    }
}

class Produser implements Runnable {
    Antrian q;
    Produser(Antrian q) {
        this.q = q;
        new Thread(this, "Produser").start();
    }

    public void run() {
        int i = 0;
        while(true) {
            q.tempatkan(i++);
        }
    }
}

class Konsumen implements Runnable {
    Antrian q;
    Konsumen(Antrian q) {
        this.q = q;
        new Thread(this, "Konsumen").start();
    }

    public void run() {
        while(true) {
            q.ambil();
        }
    }
}

public class DemoKomunikasiThread2 {
    public static void main(String args[]) {
        Antrian q = new Antrian();
        new Produser(q);
        new Konsumen(q);
       
        System.out.println("Tekan Control-C untuk menghentikan.");
    }
}

Keluaran Program

Menempatkan: 0
Tekan Control-C untuk menghentikan.
Mengambil: 0
Menempatkan: 1
Mengambil: 1
Menempatkan: 2
Mengambil: 2
Menempatkan: 3
Mengambil: 3
Menempatkan: 4
Mengambil: 4
Menempatkan: 5
Mengambil: 5
Menempatkan: 6
Mengambil: 6
Menempatkan: 7
Mengambil: 7
Menempatkan: 8
Mengambil: 8
Menempatkan: 9
Mengambil: 9
Menempatkan: 10
Mengambil: 10

10.    Tulislah sebuah program untuk menggunakan metode suspend dan resume.

Penyelesaian

// Menggunakan suspend() dan resume().
class ThreadBaru implements Runnable {
    String nama; // nama thread
    Thread t;

    ThreadBaru(String namaThread) {
        nama = namaThread;
        t = new Thread(this, nama);
        System.out.println("Thread baru: " + t);
        t.start(); // memulai thread
    }

    // ini adalah titik entri untuk thread.
    public void run() {
        try {
            for(int i = 15; i > 0; i--) {
                System.out.println(nama + ": " + i);
                Thread.sleep(200);
            }
        }
        catch (InterruptedException e) {
            System.out.println(nama + " diinterupsi.");
        }
        System.out.println(nama + " keluar.");
    }
}

public class DemoSuspendResume {
    public static void main(String args[]) {
        ThreadBaru ob1 = new ThreadBaru("Satu");
        ThreadBaru ob2 = new ThreadBaru("Dua");

        try {
            Thread.sleep(1000);
            ob1.t.suspend();
            System.out.println("Membatalkan thread Satu");
            Thread.sleep(1000);
            ob1.t.resume();
            System.out.println("Memulai thread Satu");
            ob2.t.suspend();
            System.out.println("Membatalkan thread Dua");
            Thread.sleep(1000);
            ob2.t.resume();
            System.out.println("Memulai thread Dua");
        }
        catch (InterruptedException e) {
            System.out.println("Thread main diinterupsi");
        }

        // menunggu thread-thread selesai
        try {
            System.out.println("Menunggu thread-thread selesai.");
            ob1.t.join();
            ob2.t.join();
        }
        catch (InterruptedException e) {
            System.out.println("Thread main diinterupsi");
        }

        System.out.println("Thread main keluar.");
    }
}

Keluaran Program

Thread baru: Thread[Satu,5,main]
Thread baru: Thread[Dua,5,main]
Satu: 15
Dua: 15
Satu: 14
Dua: 14
Dua: 13
Satu: 13
Dua: 12
Satu: 12
Dua: 11
Satu: 11
Dua: 10
Membatalkan thread Satu
Dua: 9
Dua: 8
Dua: 7
Dua: 6
Dua: 5
Memulai thread Satu
Membatalkan thread Dua
Satu: 10
Satu: 9
Satu: 8
Satu: 7
Satu: 6
Satu: 5
Memulai thread Dua
Menunggu thread-thread selesai.
Dua: 4
Satu: 4
Dua: 3
Satu: 3
Dua: 2
Satu: 2
Dua: 1
Satu: 1
Dua keluar.
Satu keluar.
Thread main keluar.

11.    Tulis-ulanglah kode pada soal no 10 sehingga membatalkan dan memulai lagi sebuah thread dengan cara yang lebih elegan.

Penyelesaian

// Menggunakan suspend() dan resume() dengan cara yang lebih modern
class ThreadBaru implements Runnable {
    String nama; // nama thread
    Thread t;
    boolean benderaBatal;

    ThreadBaru(String namaThread) {
        nama = namaThread;
        t = new Thread(this, nama);
        System.out.println("Thread baru: " + t);
        benderaBatal = false;
        t.start(); // memulai thread
    }

    // ini adalah titik entri untuk thread.
    public void run() {
        try {
            for(int i = 15; i > 0; i--) {
                System.out.println(nama + ": " + i);
                Thread.sleep(200);
                synchronized(this) {
                    while(benderaBatal) {
                        wait();
                    }
                }
            }
        }
        catch (InterruptedException e) {
            System.out.println(nama + " diinterupsi.");
        }
        System.out.println(nama + " keluar.");
    }
   
    void batalku() {
        benderaBatal = true;
    }

    synchronized void mulaiku() {
        benderaBatal = false;
        notify();
    }
}

public class DemoSuspendResume2 {
    public static void main(String args[]) {
        ThreadBaru ob1 = new ThreadBaru("Satu");
        ThreadBaru ob2 = new ThreadBaru("Dua");

        try {
            Thread.sleep(1000);
            ob1.batalku();
            System.out.println("Membatalkan thread Satu");
            Thread.sleep(1000);
            ob1.mulaiku();
            System.out.println("Memulai thread Satu");
            ob2.batalku();
            System.out.println("Membatalkan thread Dua");
            Thread.sleep(1000);
            ob2.mulaiku();
            System.out.println("Memulai thread Dua");
        }
        catch (InterruptedException e) {
            System.out.println("Thread main diinterupsi");
        }

        // menunggu thread-thread selesai
        try {
            System.out.println("Menunggu thread-thread selesai.");
            ob1.t.join();
            ob2.t.join();
        }
        catch (InterruptedException e) {
            System.out.println("Thread main diinterupsi");
        }

        System.out.println("Thread main keluar.");
    }
}

Keluaran Program

Thread baru: Thread[Satu,5,main]
Thread baru: Thread[Dua,5,main]
Satu: 15
Dua: 15
Dua: 14
Satu: 14
Dua: 13
Satu: 13
Satu: 12
Dua: 12
Dua: 11
Satu: 11
Dua: 10
Membatalkan thread Satu
Dua: 9
Dua: 8
Dua: 7
Dua: 6
Dua: 5
Memulai thread Satu
Membatalkan thread Dua
Satu: 10
Satu: 9
Satu: 8
Satu: 7
Satu: 6
Satu: 5
Dua: 4
Memulai thread Dua
Menunggu thread-thread selesai.
Satu: 4
Dua: 3
Satu: 3
Dua: 2
Satu: 2
Dua: 1
Dua keluar.
Satu: 1
Satu keluar.
Thread main keluar.





No comments:

Post a Comment