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





Friday, July 6, 2018

Tagged under:

Java Set – Set trong Java

Java Set – Set trong Java

Java Set là một tập hợp các phần tử hoặc đối tượng(Objects), các phần tử này không trùng lặp. Java Set là một interface được thừa kế từ Collection interface. Không giống như List, Java Set KHÔNG phải là 1 tập thứ tự, các phần tử của nó KHÔNG có một thứ tự nhất định. Java Set KHÔNG cung cấp truy cập qua vị trí, và nơi bạn chèn phần từ vào Set. Bạn không thể truy cập phần tử bằng vị trí(index) và tìm kiếm kiếm phần tử trong danh sách.

Java Set

Trong phần này, tôi sẽ trình bày về những điểm quan trọng của Java Set:

  1. Java Set interface là một thành viên(member) của Java Collections Framework.
  2. Không giống như List, Set KHÔNG cho phép bạn thêm vào những phần tử trùng lặp.
  3. Set cho phép bạn thêm duy nhất 1 phần từ null.
  4. Set interface có 1 hàm mặc định(default method) trọng Java 8: spliterator.
  5. Không giống như List và mảng(Array), Set KHÔNG hỗ trợ chỉ mục(index, position) của phần tử.
  6. Set hỗ trợ kiểu Generics và chúng ta nên sử dụng nó khi có thể. Sử dụng kiểu Generic trong Set sẽ giúp bỏ qua vấn đề ClassCastException trong thời gian chạy(runtime).
  7. Chúng ta có thể sử dụng thực thi(implementations) Set interface để duy trì những phần tử duy nhất(unique)

Biểu đồ lớp(class) của Java Set

Java Set interface kế thừa(extend) từ Collection interface. Collection interface kế thừa từ Iterable interface. Những class thường thực thi(implementation) Set là: HashSet, LinkedHashSet, TreeSet, CopyOnWriteArraySet và ConcurrentSkipListSet. AbstractSet cung cấp 1 bộ khung thực thi(implementation) của Set interface vì thế các class kế thừa AbstractSet không cần thực thi(implementation) lại.



Các hàm trong Java Set

Trong phần này tôi sẽ trình bày các hàm thông dụng trong Java Set:
int size(): Trả về số lượng phần tử trong Set.
boolean isEmpty(): Kiểm tra Set có bị rỗng hay không.
boolean contains(Object o): Trả về tru nếu phần tử được tìm thấy.
Iterator iterator(): Trả về object Iterator dùng để duyệt các phần tử trong Set. Các phần tử trả về không có thứ tự nhất định.
Object[] toArray(): Trả về mảng các phần tử trong Set. Thứ tự của các phần tử trả về trong iterator sẽ giống với thứ tự mảng.
boolean add(E e): Thêm 1 phần tử vào trong Set nếu phần tử đó chưa tồn tại trong Set.
boolean remove(Object o): Xóa 1 phần tử trong Set nếu phần tử đó tồn tại.
boolean removeAll(Collection c): Xóa tất cả các phần tử trong Set mà tồn tại trong collection.
boolean retainAll(Collection c): Chỉ giữ lại các phần tử tồn tại trong collection, các phần tử khác sẽ bị xóa bỏ.
void clear(): Xóa tất cả các phần tử trong Set.

Chuyển đổi Mảng(Array) thành Set

Không giống như List, chúng ta KHÔNG thể chuyển đổi mảng(Array) thành Set một cách trực tiếp
Vì thế chúng ta KHÔNG thể sử dụng lớp mảng(Array class) để chuyển đổi. Chúng ta có thể tiếp cận bằng cách khác. Chúng ta có thể chuyển đổi mảng(array) thành List bằng cách sử dụng hàm Arrays.asList(), sau đó sử dụng nó để tạo ra một Set. Bằng cách này, chúng ta có thể chuyển đổi 1 Java Array theo 2 cách. Chúng ta sẽ tham khảo từng cách một theo hướng dẫn dưới đây.
Cách 1:
Trong cách này, đầu tiên chúng ta cần tạo ra 1 List từ mảng cho trước và dùng nó để tạo ra 1 Set:
import java.util.*;

public class ArrayToSet {
   public static void main(String[] args) {
  
 String[] vowels = {"a","e","i","o","u"};
  
 Set<String> vowelsSet = new HashSet<String>(Arrays.asList(vowels));
 System.out.println(vowelsSet);
 
 /**
  * Unlike List, Set is Not backed by array, 
  * so we can do structural modification without any issues.
  */
 vowelsSet.remove("e");
 System.out.println(vowelsSet);
 vowelsSet.clear();
 System.out.println(vowelsSet);
   }
}
Cách 2:
Với cách tiêp cận này, chúng ta KHÔNG cần sử dụng List làm trung gian để tạo ra Set từ Array. Đầu tiên tạo một HashSet rỗng, sau đó sử dụng Collection.addAll() để copy các phần tử trong mảng vào Set.
import java.util.*;

public class ArrayToSet2 {
   public static void main(String[] args) {
  
 String[] vowels = {"a","e","i","o","u"};
  
 Set<String> vowelsSet = new HashSet<>();
 Collections.addAll(vowelsSet, vowels); 
 System.out.println(vowelsSet);

 /** 
  * Unlike List, Set is NOt backed by array, 
  * so we can do structural modification without any issues.
  */
 vowelsSet.remove("e");
 System.out.println(vowelsSet);
 vowelsSet.clear();
 System.out.println(vowelsSet);
   }
}
Kết quả:
Khi chúng ta chạy 2 chương trình trên điều xuất ra kết quả giống nhau
[a, e, u, i, o]
[a, u, i, o]
[]

Chuyển Java Set thành mảng(Array)

Trong phần này, chúng ta sẽ viết 1 chương trình chuyển một tập Set String thành Mảng(Array) String bằng cách sử dụng hàm Set.toArray() như bên dưới:
import java.util.*;

public class SetToArray {
   public static void main(String[] args) {
 Set<String> vowelsSet = new HashSet<>();

 // add example
 vowelsSet.add("a");
 vowelsSet.add("e");
 vowelsSet.add("i");
 vowelsSet.add("o");
 vowelsSet.add("u");
  
 //convert Set to Array
 String strArray[] = vowelsSet.toArray(new String[vowelsSet.size()]);
 System.out.println(Arrays.toString(strArray)); 
   }
}
Kết quả:
Khi ta chạy chương trình trên, kết quả sẽ xuất ra như sau:
[a, e, u, i, o]

Sắp xếp trong Java Set

Như chúng ta được biết Set(HashSet) KHÔNG hỗ trợ sắp xếp các phần tử một cách trực tiếp. Nó sắp xếp và hiển thị các phần tử một cách ngẫu nhiên.
Tuy nhiên ta có cách sắp xếp các phần tử như sau:
Chuyển Java Set thành List sau đó sử dụng Collections.sort() để sắp xếp mảng
import java.util.*;

public class SetSortingExample {

 public static void main(String[] args) {
  Set<Integer> intsSet = new HashSet<>();
  Random random = new Random();
  for(int i = 0; i <= 10; i++) {
 intsSet.add(random.nextInt(1000)) ;
  }
  
  System.out.println("Before Sorting: " + intsSet);
  
  List listASC = new ArrayList<Integer>(intsSet);
  
  Collections.sort(listASC, new Comparator<Integer>() {
        public int compare(Integer a, Integer b) {
        return a - b;
        }
  });
  
  System.out.println("ASC Sorting: " + listASC);
  
  List listDES = new ArrayList<Integer>(intsSet);
  
  Collections.sort(listASC, new Comparator<Integer>() {
 public int compare(Integer a, Integer b) {
  return b - a;
        }
  });
  
  System.out.println("DES Sorting: " + listASC);
 }
}

Kết quả:
Khi chúng ta chạy chương trình trên sẽ xuất ra kết quả như sau:
Before Sorting: [976, 241, 868, 518, 599, 776, 954, 939, 92, 173, 207]
ASC Sorting: [92, 173, 207, 241, 518, 599, 776, 868, 939, 954, 976]
DES Sorting: [976, 954, 939, 868, 776, 599, 518, 241, 207, 173, 92]

Java Set những toán tử thông dụng

Hầu hết những toán tử thông dụng hay được thực thi trên Java Set là add, addAll, clear, size. Dưới đây là ví dụ về những hàm hay được sử dụng trong Java Set
import java.util.*;

public class SetCommonOperations 
{
   public static void main(String args[]) 
   {
 Set<String> vowels= new HashSet<>();
  
 //add example
 vowels.add("A");
 vowels.add("E");
 vowels.add("I");

 //We cannot insert elements based on index to a Set
 System.out.println(vowels);
  
 Set<String> set = new HashSet<>();
 set.add("O");
 set.add("U");
 
 //appending set elements to letters
 vowels.addAll(set);
 System.out.println(vowels);
 
 //clear example to empty the set
 set.clear();
  
 //size example
 System.out.println("letters set size = " + vowels.size());
  
 vowels.clear();
 vowels.add("E"); vowels.add("E");vowels.add("I"); vowels.add("O");
 System.out.println("Given set contains E element or not? = " + vowels.contains("E"));
  
   }
}

Kết quả:
[A, E, I]
[A, E, U, I, O]
letters set size = 5
Given set contains E element or not? = true

Java Set duyệt các phần tử

Dưới đây là ví dụ đơn giản để duyệt các phần tử trong Java Set
import java.util.*;

public class SetIteratorExample
{
   public static void main(String[] args) 
   {

 Set<Integer> set = new HashSet<>();
 for(int i=0; i<5; i++) 
  set.add(i);
  
 Iterator iterator = set.iterator();
 
 //simple iteration
 while(iterator.hasNext()){
  int i = (int) iterator.next();
  System.out.print(i + ", ");
 }
 System.out.println("\n" + set);
 
 //modification of set using iterator
 iterator = set.iterator();
 while(iterator.hasNext()){
  int x = (int) iterator.next();
  if(x%2 ==0) iterator.remove();
 }
 System.out.println(set);
  
 //changing set structure while iterating
 iterator = set.iterator();
 while(iterator.hasNext()){
                //ConcurrentModificationException here
  int x = (int) iterator.next(); 
  if(x==1) set.add(10);
 }
   }
}

Kết quả
0, 1, 2, 3, 4, 
[0, 1, 2, 3, 4]
[1, 3]
Exception in thread "main" java.util.ConcurrentModificationException
 at java.util.HashMap$HashIterator.nextNode(Unknown Source)
 at java.util.HashMap$KeyIterator.next(Unknown Source)
 at com.vn.programming.MultipleThread.main(MultipleThread.java:33)
Đoạn dưới đây quăng lỗi ConcurrentModificationException bởi vì chứ ta không thể thay đổi cấu trúc của set khi duyệt interator
while(iterator.hasNext()){
                //ConcurrentModificationException here
  int x = (int) iterator.next(); 
  if(x==1) set.add(10);
 }

Java Set sang Stream

Ví dụ dưới đây hướng dẫn chuyển Java Set thành Stream
import java.util.*;

public class SetToStream {

   public static void main(String[] args) {
 Set<String> vowelsSet = new HashSet<>();
 // add example
 vowelsSet.add("a");
 vowelsSet.add("e");
 vowelsSet.add("i");
 vowelsSet.add("o");
 vowelsSet.add("u");
  
 //convert set to stream
 vowelsSet.stream().forEach(System.out::println);
   }
}
Kết quả
a
e
u
i
o

Monday, July 2, 2018

Tagged under:

Thread.sleep() trong Java – Java Thread sleep


Thread.sleep trong Java

  • Phương thức Thread.sleep() được sử dụng để tạm dừng thực thi của thread theo thời gian 1/1000 giây(milliseconds). Đối số milliseconds bắt buộc là số dương, nếu bạn nhập số âm sẽ xuất lỗi IllegalArgumentException.
  • Có một phương thức khác là sleep(long millis, int nanos) có thể sử dụng để tạm dừng thực thi của thread với giá trị truyền vào là 1/0000 (miniseconds) và 1 phần tỉ (nanoseconds). Giá trị của nano second là từ 0 đến 999999.

Ví dụ về Java Thread Sleep

Mình sẽ viết 1 chương trình đơn giản để tạm dừng thực thi của thread trong 2 giây.
ThreadSleep.java file.
package com.journaldev.threads;

public class ThreadSleep {

    public static void main(String[] args) throws InterruptedException {
        long start = System.currentTimeMillis();
        Thread.sleep(2000);
        System.out.println("Sleep time in ms = "+(System.currentTimeMillis()-start));
        
    }

}

Nếu bạn chạy chương trình trên thì sẽ xuất ra thời gian lớn hơn 2000. Bởi vì đó là cách hoạt động thread sleep và hệ điều hành thực thi thread scheduler.

Những điểm quan trọng của Thread Sleep

  1. Thread Sleep luôn luôn tạm dừng Thread đang thực thi.
  2. Thời gian chính xác của thread sleep trước khi gọi và bắt đầu thực thi được dựa vào thời gian và lịch trình của hệ thống (system timers và schedulers). Khi hế thống nhàn rỗi, thời gian thực của sleep gần bằng với thời gian chỉ định nhưng khi hệ thống bận thì thời gian sẽ tăng lên.
  3. Thread sleep không mất bất kỳ sự giám sát hay khóa (monitors or locks) của thread hiên tại.
  4. Bất kỳ thread nào ngắt ngang, phá vỡ (interrupt) thread trong lúc sleep, thì chương trình sẽ xuất lỗi InterruptedException.

Cách hoạt động của Thread Sleep

Thread.sleep tương tác với lịch trình thread(thread scheduler) để truyền thời gian chờ. Khi thời gian chờ kết thúc, thread chuyển sang chạy thái runnable và đợi CPU thực thi. Vì thể thời gian chính xác của thread sleep phụ thuộc và thread scheduler. Thread scheduler là 1 phần của hệ điều hành.

Nguồn: Thread sleep in java

Thursday, June 28, 2018

Tagged under:

Java Thread (Luồng trong Java)


Process và Thread là 2 thứ căn bản nhất trong thực thi. Lập trình đồng thời (concurrency programming) là một ví dụ điển hình về Thread.

Process

Process là nơi chứa đựng môi trường thực thi và có thể xem như là một chương trình hoặc là một ứng dụng. Một chương trình có thể chưa nhiều Process trong nó. JRE(Java Runtime Environment) chạy như là 1 process nơi mà chưa nhiều class và chương trình khác nhau.

Thread

Thread còn được gọi là lightweight process. Thread không yêu cầu nhiều nguồn tài nguyên để tạo và tồn tại trong process. Thread chia sẻ nguồn tài nguyên của process.

Mỗi ứng dụng Java đòi hỏi phải có ít nhất 1 Thread (main Thread). Mặt dù có nhiều loại thread chạy nền như là: bộ quản lý hệ thống, bô quản lý vùng nhớ, bộ xử lý tín hiệu. Nhưng theo góc nhìn ứng dụng, main là thread đầu tiên và chúng ta có thể tạo nhiều thread từ đó.

Multithreading(đa luồng) gồm có hai hoặc nhiều thread cùng thực thi trong một chương trình. Máy tính với 1 lõi (core) chỉ có thể thực thi một thread tại 1 thời gian và thời gian đó được chia nhỏ trong hệ điều hành để chia sẻ thời gian thực thi giữa các thread và process.

Lợi ích của Thread


  1. Thread khá nhẹ so với Process, và tốn ít thời, tài nguyên để khởi tạo 1 Thread.
  2. Thread chia sẽ dữ liệu và code của process cha.
  3. Sự chuyển đổi giữa các Thread tôn ít chi phí hơn so với Process.
  4. Sự giao tiếp giữa các Thread dễ dàng hơn so với Process.


Ta có 2 cách để tao Thread:

  1. Thực thi(implement) java.lang.Runnable interface.
  2. Thừa kế(extends) java.lang.Thread class.


Ví dụ về thực thi(implement) java.lang.Runnable interface.

Để tạo class runnable, chúng ta phải implement java.lang.Runnable interface và tiến hành thực thi(implementation) trong phương thức public void run(). Để sử dụng class như một Thread, chúng ta cần khởi tạo một đối tượng Thread bằng cách truyền class dưới đây vào Thread gọi hàm start() để thực thi hàm  run() trong mỗi Thread.

package com.journaldev.threads;

public class HeavyWorkRunnable implements Runnable {

    @Override
    public void run() {
        System.out.println("Doing heavy processing - START "+Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
            //Get database connection, delete unused data from DB
            doDBProcessing();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Doing heavy processing - END "+Thread.currentThread().getName());
    }

    private void doDBProcessing() throws InterruptedException {
        Thread.sleep(5000);
    }

}

Ví dụ về Thừa kế(extends) java.lang.Thread class

Chúng ta có thể kế thừa java.lang.Thread class để tạo một class thread riêng và kế thừa hàm run(). Sau đó chúng ta tạo một object và gọi hàm start() để thực thi Thread class vừa mới tạo.

package com.journaldev.threads;

public class MyThread extends Thread {

    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        System.out.println("MyThread - START "+Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
            //Get database connection, delete unused data from DB
            doDBProcessing();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("MyThread - END "+Thread.currentThread().getName());
    }

    private void doDBProcessing() throws InterruptedException {
        Thread.sleep(5000);
    }
    
}

Hàm main thực thi 2 ví dụ trên:

package com.journaldev.threads;

public class ThreadRunExample {

    public static void main(String[] args){
        Thread t1 = new Thread(new HeavyWorkRunnable(), "t1");
        Thread t2 = new Thread(new HeavyWorkRunnable(), "t2");
        System.out.println("Starting Runnable threads");
        t1.start();
        t2.start();
        System.out.println("Runnable Threads has been started");
        Thread t3 = new MyThread("t3");
        Thread t4 = new MyThread("t4");
        System.out.println("Starting MyThreads");
        t3.start();
        t4.start();
        System.out.println("MyThreads has been started");
        
    }
}

Kết quả chương trình:

Starting Runnable threads
Runnable Threads has been started
Doing heavy processing - START t1
Doing heavy processing - START t2
Starting MyThreads
MyThread - START Thread-0
MyThreads has been started
MyThread - START Thread-1
Doing heavy processing - END t2
MyThread - END Thread-1
MyThread - END Thread-0
Doing heavy processing - END t1

Khi chúng ta khởi động thread, nó sẽ thực thi dựa theo hệ điều hành thực thi với thời gian chia nhỏ cho mỗi thread, chúng ta không thể điều khiển vấn đề này. Tuy nhiên chúng ta có thể xét độ ưu tiên, nhưng điều này không đảm bảo những thread có độ ưu tiên cao sẽ được thực thi trước.

Chạy chương trình trên nhiều lần bạn sẽ thấy mỗi lần chạy sẽ xuất ra kết quả khác nhau, không có qui luật cụ thể.

Runnable và Thread

Nếu class của bạn thiên về chức năng hơn là chạy Thread, bạn nên implement Runnable interface. Nếu mục đích class của bạn là để chạy như Thread, thì bạn có thể extends(thừa kế)Thread.

Thực thi(Implement) Runnable đựa ưu tiên hơn vì java có thể thực thi(implememt) nhiều interface. Nếu bạn thừa kế(extends) class, thì bạn không thể thừa kế bất ký class nào khác.

Mẹo:Như bạn đã thấy Thread không trả về(return) bất kỳ giá trị nào, nhưng nếu bạn muốn class xử lý một vài chức năng sau đó trả về(return) giá trị. Chúng ta sẽ tham khảo bài viết kế tiếp.

Ghi Chú: Từ java 8 trở đi ta có thể sử dụng lambda expression để thực thi (implement) hơn là sử dụng class ẩn danh(anonymous)

Nguồn: Java Thread example





















Thursday, June 21, 2018

Tagged under:

Cài đặt Docker cho Windows

1. Giới thiệu về Docker:

Bạn mệt mỏi về vấn đề cài đặt, thiết lập môi trường. Mỗi lần gửi cho khách hàng bạn hỗ trợ support có thể là 1 tuần hoặc là 1 tháng. Với Docker thì chỉ cần vài dòng lệnh, sẽ tạo cho bạn môi trường ảo hóa và tất cả đã xong. Done!

2. Cài Đặt Docker

Để cài đặt Docker đầu tiên bạn phải có tài khoản Docker được đăng ký tại địa chỉ:
https://store.docker.com/signup

Sau khi đăng ký thành công thì bạn tiến hành download Docker tại địa chỉ:
https://store.docker.com/editions/community/docker-ce-desktop-windows

Trước khi download Docker yêu cầu bạn phải đăng nhập:
Click vào nút Please Login To Download để tiến hành đăng nhập


Sau khi đăng nhập thành công bạn click vào nút Get Docker để tiền hành download


Sau khi download xong bạn click vào file Docker for Windows Installer.exe để tiến hành cài đặt
Chọn như hình và bấm nút OK


Quá trình cài đặt diễn ra trong vài phút và thông báo thành công như hình dưới:


Tiền hành khởi động Docker lên bạn sẽ thấy icon như hình:











Tiền hành đăng nhập tài khoản và mật khẩu Docker mà bạn đã tạo trước đó:




Để kiểm tra version bạn gõ lệnh sau trong command line: docker --version

Chúc mừng bạn đã cài đặt thành công!
Mọi thắc mắc các bạn vui lòng để lại comment bên dưới.