300x250 AD TOP

Thank you so much for taking the time for sharing your knowledge with me

Powered by Blogger.

Sunday, August 19, 2018

Tagged under:

Hướng dẫn Java Thread wait, notify và notifyAll

Lớp đối tượng trong java gồm có 3 hàm final cho phép thread kết nối với trạng thái khóa, mở. Những hàm này bao gồm wait(), notify(), và notifyAll(). Hôm nay chúng ta sẽ tìm hiểu về chương trình java của của các hàm wait, notify và notifyAll.

Wait, notify and notifyAll trong Java


Thread chứa những hàm trên sẽ có mội đối tượng kiểm soát, nếu không sẽ quăng lỗi java.lang.IllegalMonitorStateException.

Wait

Hàm wait gồm có 3 thành phần, thành phần đâu tiên sẽ đợi thread gọi hàm notify hoặc notifyall để đánh thức thread hiện tại. 2 thành phần còn lại sẽ được truyền vào thời gian để đánh thức thread.

Notify

Hàm notify chỉ đánh thức 1 thread đang chờ. Nếu có nhiều thread đang chờ, hàm này chỉ đánh thức 1 trong số đó. Sự lựa chọn thread đánh thức phụ thuộc vào hệ hiểu hành.

NotifyAll

Hàm notifyAll sẽ đanh thức tất cả các thraed đang chờ, thread nào được đánh thức đầu tiên sẽ tùy thuộc vào hệ điều hành.

Những hàm này có thể sử dụng để thực thi vấn đề producer consumer nơi mà consumer thread đợi một đối tượng trong Queue và producer thread thêm đối tượng vào queue và thông báo với thread đang đợi(consumer).

Dưới đây là ví dụ về nhiều thread trên cùng một đối tượng và chúng ta sẽ sử dụng hàm wait, notify và notifyall.

Message

Lớp java bean mà thread sẽ gọi hàm wait, notify, notifyall.


package com.journaldev.concurrency;

public class Message {
    private String msg;
    
    public Message(String str){
        this.msg=str;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String str) {
        this.msg=str;
    }

}


Waiter

Lớp này sẽ đợi thread gọi hàm notify để thực thi. Lưu ý rằng thread waiter sẽ có sự điều khiển đối tượng  Message của chính nó bằng cách sử dụng synchronized.

package com.journaldev.concurrency;

public class Waiter implements Runnable{
    
    private Message msg;
    
    public Waiter(Message m){
        this.msg=m;
    }

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        synchronized (msg) {
            try{
                System.out.println(name+" waiting to get notified at time:"+System.currentTimeMillis());
                msg.wait();
            }catch(InterruptedException e){
                e.printStackTrace();
            }
            System.out.println(name+" waiter thread got notified at time:"+System.currentTimeMillis());
            //process the message now
            System.out.println(name+" processed: "+msg.getMsg());
        }
    }

}

Notifier

Lớp này sẽ xử lý đối tượng Message và gọi hàm notify để đánh thức thead đối tượng Message đang chờ. Lưu ý rắng synchronized được sử dụng kiểm soát đổi tượng Message của chính nó.

package com.journaldev.concurrency;

public class Notifier implements Runnable {

    private Message msg;
    
    public Notifier(Message msg) {
        this.msg = msg;
    }

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(name+" started");
        try {
            Thread.sleep(1000);
            synchronized (msg) {
                msg.setMsg(name+" Notifier work done");
                msg.notify();
                // msg.notifyAll();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
    }

}

WaitNotifyTest

Lớp kiểm tra này sẽ được sử dụng để tạo ra nhiều thread của waiter và notifer và sau đó khởi động chúng.


package com.journaldev.concurrency;

public class WaitNotifyTest {

    public static void main(String[] args) {
        Message msg = new Message("process it");
        Waiter waiter = new Waiter(msg);
        new Thread(waiter,"waiter").start();
        
        Waiter waiter1 = new Waiter(msg);
        new Thread(waiter1, "waiter1").start();
        
        Notifier notifier = new Notifier(msg);
        new Thread(notifier, "notifier").start();
        System.out.println("All the threads are started");
    }

}
Khi chúng ta gọi hàm trên, kết quả sẽ hiển thị như bên dưới và chương trình sẽ chạy không thành công bởi vì có 2 thread đang đợi trên đối tượng Message và hàm notify chỉ đánh thức 1 trong số chúng, thread còn lại vẫn chờ để được đánh thức.

waiter waiting to get notified at time:1356318734009
waiter1 waiting to get notified at time:1356318734010
All the threads are started
notifier started
waiter waiter thread got notified at time:1356318735011
waiter processed: notifier Notifier work done
Nếu chúng ta comment hàm notify() và mở comment hàm notifyAll() thì kết quả sẽ được hiển thị như bên dưới.
Copy
waiter waiting to get notified at time:1356318917118 waiter1 waiting to get notified at time:1356318917118 All the threads are started notifier started waiter1 waiter thread got notified at time:1356318918120 waiter1 processed: notifier Notifier work done waiter waiter thread got notified at time:1356318918120 waiter processed: notifier Notifier work done
Hàm notifyAll() sẽ đánh thức 2 thread đang chờ và chương trình sẽ kết thúc sau khi thực thi.

Saturday, August 18, 2018

Tagged under:

Hướng dẫn Java BlockingQueue

Hôm nay chúng ta sẽ tìm hiểu về Java Blocking Queue. java.util.concerrent.BlockingQueue là java Queue hỗ trợ sự điều khiển: nó sẽ đợi đến khi queue khác rỗng trong trường hợp lấy hoặc xóa dữ liệu, và sẽ đợi đến khi có đủ không gian chứa khi thực thi thêm dữ liệu.

Java BlockingQueue


Java BlockingQueue không chấp nhận giá trị null và sẽ quăng lỗi NulPointerException nếu lưu dữ liệu null vào queue

Java BlockingQueue an toàn trong với thread. Tất cả các hàm của queue nguyên bản một cách tự nhiên, sử dụng khóa ở phía trong hoặc các định dạng khác của điều khiển đồng thời.

Java BlockingQueue interface là một phần của java collection framework và nó được sử dụng chính cho vấn đề sản xuất(producer) và tiêu thụ(consumer). Chúng ta không cần quan tâm về vấn đề đợi đến khi có đủ không gian cho producer hoặc đối tượng có tồn tại hay không cho consumer trong BlockingQueue bởi vì nó được sử lý bằng cách thực thi các lớp của BlockingQueue.

Java cung cấp nhiều lớp thực thi của BlockingQueue như là ArrayBlockingQueue, LinkedBlockingQueue, PriorityBlockingQueue, SynchronousQueue.

Khi thực thi producer và consumer trong BlockingQueue, chúng ta sẽ sử dụng ArrayBlockingQueue. Dưới đây là những hàm quan trọng bạn cần phải biết:

put(E e): Hàm này được sử dụng để thêm phần từ vào queue. Nếu queue đầy, thì nó sẽ đợi cho đến khi có đủ không gian trống.

E take(): Hàm này được sử dụng để lấy ra và xóa 1 phần tử đứng đầu trong queue. Nếu queue rỗng nó sẽ đợi cho đến khi nào có phần tử trong queue.

Và bây giờ chúng ta sẽ tiền hành thực thi về vấn đề producer consumer sử dụng java Blocking Queue.

Ví dụ về Java BlockingQueue – Message


Như là 1 đối tượng java bình thường sẽ được tạo ra bởi Producer và thêm vào queue. Bạn có thể xem nó như là 1 queue message.

package com.journaldev.concurrency;

public class Message {
    private String msg;
    
    public Message(String str){
        this.msg=str;
    }

    public String getMsg() {
        return msg;
    }

}


Ví dụ về Java BlockingQueue – Producer


Lớp Producer sẽ tạo ra message và thêm vào queue.


package com.journaldev.concurrency;

import java.util.concurrent.BlockingQueue;

public class Producer implements Runnable {

    private BlockingQueue<Message> queue;
    
    public Producer(BlockingQueue<Message> q){
        this.queue=q;
    }
    @Override
    public void run() {
        //produce messages
        for(int i=0; i<100; i++){
            Message msg = new Message(""+i);
            try {
                Thread.sleep(i);
                queue.put(msg);
                System.out.println("Produced "+msg.getMsg());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //adding exit message
        Message msg = new Message("exit");
        try {
            queue.put(msg);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

Ví dụ về Java BlockingQueue – Consumer


Lớp Consumer sẽ xử lý message từ queue và kết thúc chương trình khi nhận được message là exit.

package com.journaldev.concurrency;

import java.util.concurrent.BlockingQueue;

public class Consumer implements Runnable{

private BlockingQueue<Message> queue;
    
    public Consumer(BlockingQueue<Message> q){
        this.queue=q;
    }

    @Override
    public void run() {
        try{
            Message msg;
            //consuming messages until exit message is received
            while((msg = queue.take()).getMsg() !="exit"){
            Thread.sleep(10);
            System.out.println("Consumed "+msg.getMsg());
            }
        }catch(InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Ví dụ về Java BlockingQueue – Service


Cuối cùng chúng ta sẽ tạo là một service cho producer và consumer. Service này sẽ tạo BlockingQueue với kích thước chỉ định và được truyền vào cho producer consumer. Service này sẽ khởi chạy producer consumer và sau đó là kết thúc chúng.

package com.journaldev.concurrency;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class ProducerConsumerService {

    public static void main(String[] args) {
        //Creating BlockingQueue of size 10
        BlockingQueue<Message> queue = new ArrayBlockingQueue<>(10);
        Producer producer = new Producer(queue);
        Consumer consumer = new Consumer(queue);
        //starting producer to produce messages in queue
        new Thread(producer).start();
        //starting consumer to consume messages from queue
        new Thread(consumer).start();
        System.out.println("Producer and Consumer has been started");
    }

}

Kết quả:

Producer and Consumer has been started
Produced 0
Produced 1
Produced 2
Produced 3
Consumed 0
Produced 4
Produced 5
Consumed 1
Produced 6
Produced 7
Consumed 2
Produced 8
Consumed 3
Produced 9
Consumed 4
Produced 10
Consumed 5
Produced 11
Consumed 6
Produced 12
Consumed 7
Consumed 8
Produced 13
Consumed 9
Produced 14
Consumed 10
Consumed 11
Produced 15
Consumed 12
Produced 16
Consumed 13
Produced 17
Consumed 14
Consumed 15
Produced 18
Consumed 16
Consumed 17
Produced 19
Consumed 18
Consumed 19
Produced 20
Consumed 20
Produced 21
Consumed 21
Produced 22
Consumed 22
Produced 23
Consumed 23
Produced 24
Consumed 24
Produced 25
Consumed 25
Produced 26
Consumed 26
Produced 27
Consumed 27
Produced 28
Consumed 28
Produced 29
Consumed 29
Produced 30
Consumed 30
Produced 31
Consumed 31
Produced 32
Consumed 32
Produced 33
Consumed 33
Produced 34
Consumed 34
Produced 35
Consumed 35
Produced 36
Consumed 36
Produced 37
Consumed 37
Produced 38
Consumed 38
Produced 39
Consumed 39
Produced 40
Consumed 40
Produced 41
Consumed 41
Produced 42
Consumed 42
Produced 43
Consumed 43
Produced 44
Consumed 44
Produced 45
Consumed 45
Produced 46
Consumed 46
Produced 47
Consumed 47
Produced 48
Consumed 48
Produced 49
Consumed 49
Produced 50
Consumed 50
Produced 51
Consumed 51
Produced 52
Consumed 52
Produced 53
Consumed 53
Produced 54
Consumed 54
Produced 55
Consumed 55
Produced 56
Consumed 56
Produced 57
Consumed 57
Produced 58
Consumed 58
Produced 59
Consumed 59
Produced 60
Consumed 60
Produced 61
Consumed 61
Produced 62
Consumed 62
Produced 63
Consumed 63
Produced 64
Consumed 64
Produced 65
Consumed 65
Produced 66
Consumed 66
Produced 67
Consumed 67
Produced 68
Consumed 68
Produced 69
Consumed 69
Produced 70
Consumed 70
Produced 71
Consumed 71
Produced 72
Consumed 72
Produced 73
Consumed 73
Produced 74
Consumed 74
Produced 75
Consumed 75
Produced 76
Consumed 76
Produced 77
Consumed 77
Produced 78
Consumed 78
Produced 79
Consumed 79
Produced 80
Consumed 80
Produced 81
Consumed 81
Produced 82
Consumed 82
Produced 83
Consumed 83
Produced 84
Consumed 84
Produced 85
Consumed 85
Produced 86
Consumed 86
Produced 87
Consumed 87
Produced 88
Consumed 88
Produced 89
Consumed 89
Produced 90
Consumed 90
Produced 91
Consumed 91
Produced 92
Consumed 92
Produced 93
Consumed 93
Produced 94
Consumed 94
Produced 95
Consumed 95
Produced 96
Consumed 96
Produced 97
Consumed 97
Produced 98
Consumed 98
Produced 99
Consumed 99


Thursday, August 16, 2018

Tagged under:

Java Thread Join

Hàm Java Thread join sử dụng để chạy thread hiện tại đến khi kết thúc, thì các thread khác mới chạy được. Có 3 hàn join overloaded

Java Thread Join


public final void join(): Hàm java thread join này dùng để chạy thread hiện tại đến hết luồng, thì các thread khác mới chạy được. Nếu thread bị ngắt quãng thì sẽ quăng lỗi InterruptedException.

public final synchronized void join(long millis): Hàm java thread join này dùng để chạy thread hiện tại hết khi hết luồng hoặc hết thời gian chỉ định bằng tham số được truyền vào 1/1000 giây (số truyền vào phải là số dương). Vì thời gian thực thi dựa theo hệ điều hành, nên sẽ không đảm bảo rằng thread hiện tại sẽ đợi chính xác tuyệt đối với thời gian truyền vào.

public final synchronized void join(long millis, int nanos): Hàm java thread join này dùng để chạy thread hiện tại hết khi hết luồng hoặc hết thời gian chỉ định bằng tham số được truyền vào 1/1000 giây và 1/ tỉ giây (2 tham sô này phải là số dương).

Dưới đây là ví dụ về hàm Thread Join. Mục đích của hàm này là: để chắc rằng tất cả các thread đều chạy hoàn tất và thread thứ 3 bắt đầu khi thread thứ 1 kết thúc.


package com.journaldev.threads;

public class ThreadJoinExample {

    public static void main(String[] args) {
        Thread t1 = new Thread(new MyRunnable(), "t1");
        Thread t2 = new Thread(new MyRunnable(), "t2");
        Thread t3 = new Thread(new MyRunnable(), "t3");
        
        t1.start();
        
        //start second thread after waiting for 2 seconds or if it's dead
        try {
            t1.join(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        t2.start();
        
        //start third thread only when first thread is dead
        try {
            t1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        t3.start();
        
        //let all threads finish execution before finishing main thread
        try {
            t1.join();
            t2.join();
            t3.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        System.out.println("All threads are dead, exiting main thread");
    }

}

class MyRunnable implements Runnable{

    @Override
    public void run() {
        System.out.println("Thread started:::"+Thread.currentThread().getName());
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Thread ended:::"+Thread.currentThread().getName());
    }
    
}



Kết quả của chương trình trên:


Thread started:::t1
Thread started:::t2
Thread ended:::t1
Thread started:::t3
Thread ended:::t2
Thread ended:::t3
All threads are dead, exiting main thread