Thứ Tư, 26 tháng 3, 2014

[LTM] Chương 6 : Java Threads


  1. Multitasking vs MultiThreading
  2. Define a thread
  3. Define multithreading
  4. List benefits of multithreading
  5. Create threads
  6. Discuss thread states
  7. Manage threads
  8. Explain how to set thread priorities
  9. Describe a daemon thread


[LTM] Chương 6.8: Explain how to set thread priorities (Thiết lập ưu tiên các luồng)

Methods: wait , notify 
Cơ chế chiếm dụng đồng bộ hóa ngăn cho các tuyến đoạn chồng chéo nhau. 
Các tuyến đoạn vẫn có thể trao đổi thông tin với nhau, sử dụng các phương thức:
 wait()
notify()
notifyAll()
Các phương thức này được định nghĩa trong lớp Object và được thừa kế từ các lớp Object.
public final void wait(long timeout) throws InterruptedException:
Tuyến đoạn hiện thời chờ cho tới khi được cảnh báo hoặc một khoảng thời gian timeout nhất định. 
Nếu timeout bằng 0 thì phương thức sẽ chỉ chờ cho tới khi có cảnh báo về sự kiện. 
public final void notify() 
Cảnh báo ít nhất một tuyến đoạn đang chờ một điều kiện nào đó thay đổi trước khi có thể gọi phương thức wait nào đó.  
public final void notifyAll() 
Cảnh báo tất cả các tuyến đoạn đang chờ một điều kiện thay đổi
Trong số các tuyến đoạn đã được cảnh báo, tuyến đoạn nào có độ ưu tiên cao nhất thì sẽ chạy trước tiên.

Synchronization with wait & notify
Ex: wait , notify



Ex: Synchonized with wait, notify

Bài toán Producer – Consumer.
Product: 
 get
 set(i)
Producer: set Product
Consumer: get Product 

Ex, Synchonoized (syncho_full.java) 



[LTM] Chương 6.9 : Describe a daemon thread (Mô tả 1 luồng)

Thread PRIORITY

Java gán cho mỗi tuyến đoạn một độ ưu tiên để xác định cách tuyến đoạn đó được xử lý như thế nào so với các tuyến đoạn khác.
Mỗi thread mới thừa kế quyền ưu tiên mà thread đã tạo ra nó.
A thread with a greater priority value will be run in preference to a thread with a smaller priority
Hằng số:

  • public static final int MIN_PRIORITY = 1; 
  • public static final int NORM_PRIORITY = 5; 
  • public static final int MAX_PRIORITY = 10;

Java gán cho mỗi tuyến đoạn một độ ưu tiên để xác định cách tuyến đoạn đó được xử lý như thế nào so với các tuyến đoạn khác. 
Mỗi thread mới thừa kế quyền ưu tiên mà thread đã tạo ra nó.
A thread with a greater priority value will be run in preference to a thread with a smaller priority
Hằng số:
  • public static final int MIN_PRIORITY = 1; 
  • public static final int NORM_PRIORITY = 5; 
  • public static final int MAX_PRIORITY = 10;
Phương thức:
  • setPriority(): thiết lập độ ưu tiên của tuyến đoạn hiện thời
  • getPriority(): nhận về độ ưu tiên của một tuyến đoạn
  • public static void sleep(long ms) throws InterruptedException :đưa tiến đoạn hiện hành vào trạng thái nghỉ tối thiểu là ms (mili  giây). 

Bế tắc-Deadlock
Deadlock: 
Một kiểu lỗi đặc biệt cần phải tránh có liên quan đến đa nhiệm, 
Xảy ra khi hai tuyến đoạn có một sự phụ thuộc xoay vòng trên một cặp đối tượng đồng bộ. 
Ví dụ, một tuyến đoạn chiếm dụng đối tượng X và một tuyến đoạn chiếm dụng đối tượng Y. 
 Nếu tuyến đoạn chiếm dụng X cố gắng gọi bất kỳ phương thức đồng bộ trên Y, thì nó sẽ bị phong tỏa.
 Nếu tuyến đoạn chiếm dụng Y gọi phương thức đồng bộ trên X, tuyến đoạn sẽ chờ vô hạn.
 Tuyến đoạn này chờ tuyến đoạn kia giải phóng đối tượng mà đối tượng kia đang bị chiếm dụng và ngược lại -> chờ đợi lẫn nhau (hoài vọng).

 Ex, Deadlock
Cần hạn chế deadlock:
  • Đưa ra và cải tiến việc cấp phát, 
  • thu hồi tài nguyên cho các thread 
  • khá nhiều thuật toán cải tiến việc này
Interrupt a Thread (gián đoạn)
Khi gọi phương thức Thread.sleep(int): đặt tuyến đoạn vào trạng thái nghỉ trong một khoảng thời gian xác định nào đó. 
Tuy nhiên để kích hoạt một tuyến đoạn sớm hơn ta phải sử dụng ngắt  tuyến đoạn. 
  • Phương thức interrupt(). 
  • Cần một tuyến đoạn khác tham chiếu tới tuyến đoạn hiện thời.
Ex: interrupt
Conditions thread not execute (Điều kiện không thực hiện)
If thread is:
  • Not of highest priority
  • Put to sleep using sleep() method
  • Is waiting because wait() method was called
  • Explicitly yielded using yield() method
  • Blocked for file I/O
Stop a Thread

Đôi khi cần thiết phải kết thúc một tuyến đoạn trước khi tác vụ của nó hoàn thành. 
  • Phương thức Thread.stop(). 
  • Đòi hỏi tuyến đoạn điều khiển duy trì một tham chiếu tới tuyến đoạn mà nó muốn dừng. 
Ex: stop Thread 
Review: Cycle of Thread
ThreadGroup

Constructor:
  • public ThreadGroup(String name) throws java.lang.SecurityException : Tạo ra một nhóm tuyến đoạn mới, có tên được xác định bởi  name. 
  • ThreadGroup(ThreadGroup parentGroup,String name) throws java.lang.SecurityException 
Tạo ra một nhóm tuyến đoạn mới name là nhóm con của ParentGroup
Ex:
ThreadGroup parent = new ThreadGroup("parent"); 
ThreadGroup subgroup = new ThreadGroup(parent, "sub");
Sử dụng một ThreadGroup 
Một nhóm tuyến đoạn có thể được sử dụng như một tuyến đoạn bình thường. 
Ta có thể tạm dừng, phục hồi, ngắt hoặc dừng nhóm tuyến đoạn bằng cách gọi phương thức thích hợp. 
Các phương thức 
int activeCount(): trả về số tuyến đoạn trong nhóm, và các nhóm con. 
int activeGroupCount(): trả về số nhóm con các tuyến đoạn 
boolean allowThreadSuspension(): chỉ ra tuyến đoạn bị tạm ngừng hay không. 
Ex: ThreadGroup
Daemon threads
Two types of threads in Java:

  • User threads: created by the user
  • Daemon threads: threads that work in the background providing service to other threads

e.g. – the garbage collector thread
When user thread exits, JVM checks to find out if any other thread is running.

  • If there are, it will schedule the next thread.
  • If the only executing threads are daemon threads, it exits.

We can set a thread to be a Daemon if we do not want the main program to wait until a thread ends.
Thread class has two methods to deal with Daemon threads:
  • public final void setDaemon(boolean value) : sets a thread to be a daemon thread
  • public final boolean isDaemon() : checks if the given thread is a daemon thread
Ex: Objex.isDaemon()
Daemon threads, ex

[LTM] Chương 6.7 : Manage threads (Quản lý luồng)


Synchronization - Introduction
MultiThreads:
Các tuyến đoạn có thể truy xuất tới tài nguyên dùng chung để cùng làm việc hợp tác với nhau.
Nảy sinh vấn đề gì?
Example:
Consider a simple class called Counter

 Example, expl: 
The single expression c++ can be
  • Retrieve the current value of c.
  • Increment the retrieved value by 1.
  • Store the incremented value back in c.
Ex, Thread A invokes increment at about the same time Thread B invokes decrement. If the initial value of c is 0, 
  • Thread A: Retrieve c.
  • Thread B: Retrieve c.
  • Thread A: Increment retrieved value; result is 1.
  • Thread B: Decrement retrieved value; result is -1.
  • Thread A: Store result in c; c is now 1.
  • Thread B: Store result in c; c is now -1.

Synchronization

Khi làm việc với nhiều Thread, có thể có một số Thread muốn sử dụng cùng tài nguyên tại cùng 1 time.
Khi hai tuyến đoạn cần sử dụng cùng một đối tượng, có một khả năng có các thao tác đan xen nhau làm phá hỏng dữ liệu => Race condition. ex,
Cần phải có sự đồng bộ - Synchronization.exp,
Tại một time t chỉ có 1 thread sử dụng tài nguyên.
Monitor: Chỉ có 1 Thread có được monitor tại 1 time. Các Thread khác muốn có được monitor phải chờ đợi.

Method synchronized() 

Sử dụng phương thức chiếm dụng đối tượng:
 Nếu một đối tượng bị phong tỏa (used) bởi một tuyến đoạn nào đó thì chỉ có tuyến đoạn đó mới được truy cập tới đối tượng.
Nếu một tuyến đoạn kích hoạt một phương thức synchronized trên một đối tượng, đối tượng đó sẽ bị chiếm dụng bởi tuyến đoạn kích hoạt.
Khi đối tượng được giải phóng, một tuyến đoạn khác mới được kích hoạt synchronized trên cùng đối tượng
synchronized(Obj);
Note that constructors cannot be synchronized 

Ex: test with syn and unsyn



Lệnh synchronized

Lệnh synchronized cho phép đồng bộ hóa một đối tượng thay cho phương thức synchronized
Cú pháp 
synchronized (expr) 
  { //code will execute in one thread at //a time and someObject will be locked.
}

Lệnh synchronized, ex


[LTM] Chương 6.6 : Discuss thread states (Các trạng thái của luồng)

Six states of Thread

Every Thread has a state and a Thread can be in one of these six states.

  1. new. A state in which a thread has not been started. 
  2. runnable. A state in which a thread is executing. 
  3. blocked. A state in which a thread is waiting for a lock to access an object. 
  4. waiting. A state in which a thread is waiting indefinitely for another thread to perform an action. 
  5. timed_waiting. A state in which a thread is waiting for up to a specified period of time for another thread to perform an action. 
  6. terminated. A state in which a thread has exited.

The New Thread State

  • Tạo tuyến đoạn mới: Thread newThr= new Thread(“threadName“);
  • Kích hoạt tuyến đoạn khởi động : newThread.start();
  • Khi tuyến đoạn ở trạng thái New thì chỉ có phương thức start() được gọi, nếu không sẽ có ngoại lệ IllegalThreadStateException  được đưa ra
The Runnable thread state
Một tuyến đoạn ở trạng thái runnable mỗi khi phương thức start() của nó được kích hoạt. 


Khi đó: mã lệnh trong phương thức run() (not start()) có thể được xử lý bất kỳ khi nào giành được quyền xử lý từ hệ điều hành. 
The not Runnable Thread State
Một tuyến đoạn ở not runnable state (blocked) khi:
  • Phương thức sleep() của tuyến đoạn được gọi: Tuyến đoạn sẽ tạm dừng sau một số ms xác định. 
  • Tuyến đoạn gọi phương thức wait() của một đối tượng: Tuyến đoạn sẽ not runnable cho tới khi phương thức notify() hoặc notifyAll() được gọi từ một tuyến đoạn khác. 
  • Tuyến đoạn bị blocked() bởi một thao tác vào/ra. Tuyến đoạn sẽ not runnable cho tới khi hoạt động vào ra hoàn thành.
The Dead Thread State
A thread có thể dead or alive. 
Dead khi phương thức run() hoàn thành việc xử lý.
Dead khi gán giá trị null cho đối tượng 
Phương thức isAlive(): xác định một thread còn sống hay ko
Một thread ở trạng thái dead không thể được khởi động lại.
Different thread states
Main Thread
Mỗi khi chạy một ứng dụng trong java thì đã có một thread. 
Đây là thread chính, nó thực thi các dòng lệnh trong method : public static void main . Đây là một điểm nhập bắt buộc cho mọi ứng dụng độc lập. main thread : Tuyến đoạn đầu tiên thực hiện trong ứng dụng đa tuyến đoạn, được tạo ra tự động
User thread: Người dùng tạo threads
currentThread(): phương thức được dùng để truy nhập vào main thread.

Some methods of thread class
final boolean isAlive(): kiểm tra thread còn chạy không.

final String getName(): trả về tên của thread.

final void setName(String name): thiết đặt tên cho thread

[LTM] Chương 6.5: Create threads (Tạo luồng)

Thread in Java


  • Java là một trong số nhỏ ngôn ngữ cung cấp sự hỗ trợ tại cấp ngôn ngữ cho việc tạo và quản lý luồng. 
  • Tuy nhiên, vì các luồng được quản lý bởi máy ảo Java (JVM), không bởi một thư viện cấp người dùng hay nhân.
  • Một chương trình Java có ít nhất 1 Thread, nó được gọi thực hiện khi phương thức main chạy (như một luồng đơn trong máy ảo Java) 
  • -> Main Thread. 
  • Ngoài ra, Java cung cấp các lệnh cho phép người phát triển tạo và thao tác các luồng điều khiển bổ sung trong chương trình
Create Thread

Có thể 2 cách:
Extend the java.lang.Thread class
override the run() method of the Thread class.
Implement the java.lang.Runnable interface
define the run() method.


Cách 1: Dùng Thread class

 Lớp java.lang.Thread cung cấp các phương thức quản lý, kiểm soát độ ưu tiên của tuyến đoạn :

  • khởi động (start()), 
  • tạm dừng (suspend()), 
  • phục hồi (resume()) và 
  • dừng hẳn (stop()). 

Để sử dụng lớp Thread là thừa kế lớp này và nạp chồng phương thức run():

  • Nó được gọi khi khởi động tuyến đoạn lần đầu. 
  • Một tuyến đoạn có thể thực hiện một số tác vụ hữu ích ở hậu trường



class C1 extends Thread 
   public C1(){this.start();} 
   public void run(){...} 
}
void start(): Gọi một thread khởi động
The start() method returns immediately after starting the new thread of control, without waiting for the thread to terminate 

Thread class, ex
Start() vs. run() 
Note that calling HelloThread.start() is very different from calling HelloThread.run():
Calling HelloThread.run() would execute the run() method in the same thread, rather thancreating a new thread. 
This means that all the work of the run() will be done before the computer moves on to the statements that follow the call to HelloThread.run(). 
=>There is no parallelism and no indeterminacy

Creating and Running Threads
Ex MultiThread (same task)
Ex MultiThread:

Mỗi Thread tạo ra đều thực thi các tác vụ giống nhau (theo run())
Muốn mỗi Thread thực hiện một tác vụ khác nhau?
  • Tạo các method riêng cho các thread
  • Tạo constructor, giá trị truyền vào khác nhau
  • Tạo các thread ở các class khác nhau, viết run() riêng cho mỗi thread.
  •  
Ex, Multithreads. 

Ex, MyThread_parent, MyThread_child

It is important to note that these messages can be printed in either order. 
The two threads run simultaneously and will compete for access to standard output, so that they can print their Messages
In single-threaded program, things happen in a definite, predictable order from beginning to end. 
In a multi-threaded program, there is a fundamental indeterminacy. You can’t be sure what order things will happen in

MultiThread using Array
Ex, MultiThread Array (same task)
ex :
MultiThread in multitask, 
ex: CountUC_Thread
int processors = Runtime.getRuntime().availableProcessors();
 long start = System.currentTimeMillis();
long elapsedTime = System.currentTimeMillis() - start;

Some methods of thread class 

final void join() throws InterruptedException: 
làm cho thread gọi join() (thread khác) phải ngưng hoạt động và chờ trong một khoảng thời gian, hoặc đến khi thread này kết thúc thì mới tiếp tục hoạt động
Mean: another thread calls thrd.join(), that other thread will go to sleep until thrd terminates. If thrd is already dead when thrd.join() is called, then it simply has no effect 

final void join(m) throws InterruptedException
A call to thrd.join(m) will wait until either thrd has
terminated or until m milliseconds have elapsed.
Ex: 
System.out.print("Running the thread ");
thrd.start();
while (thrd.isAlive()) {
try { thrd.join(2000); System.out.print("."); } catch (InterruptedException e) { }
  }
System.out.println(" Done!");

static void yield(): 
giành lấy quyền thực thi của tuyến đoạn hiện hành cho một trong các tuyến đoạn khác (sleep). 

final boolean isDaemon(): 
kiểm tra Daemon thread.

static int activeCount(): 
trả về số thread đang active.

static void sleep(): 
đưa tiến đoạn hiện hành vào trạng thái nghỉ tối thiểu là ms

Cách 2: Dùng Interface Runnable 
Interface  Runnable

  • định nghĩa duy nhất một phương thức run(). 
  • Các lớp thực thi giao tiếp này chỉ ra rằng chúng có thể chạy độc lập như một tuyến đoạn riêng. 
  • Báo hiệu các lớp thực thi giao tiếp này có thể chạy như các tuyến đoạn. 
  • Có thể thừa kế từ một lớp khác - đa kế thừa
  • Cùng một đối tượng Runnable có thể được truyền cho nhiều tuyến đoạn, vì vậy một số tuyến đoạn tương tranh có thể sử dụng chung mã và thao tác trên cùng dữ liệu. 

Cách định nghĩa
class C2 implements Runnable 
   public C2()
{Thread t = new Thread(this);} 
   public void run(){...} 
}
Runnable, ex
Ex: Interface Runnable 
Ex: not implement Runnable Interface

MultiThread trong Applet - ex
Hiện thị giá trị number giảm dần: 100->1
(extend: Hình ảnh đồng hồ đếm ngược)



File Thread_App_ex.java


[LTM] Chương 6.4: List benefits of multithreading (Danh sách lợi ích đa luồng)


Benefits of Multithreading (Lợi ích đa luồng)
Sự đáp ứng: 

  • MultiThread một ứng dụng giao tiếp cho phép một chương trình tiếp tục chạy thậm chí nếu một phần của nó bị khóa (wait) hay đang thực hiện một thao tác dài, 
  • do đó gia tăng sự đáp ứng đối với người dùng.. 
  • Chia sẻ tài nguyên: Thuận lợi của việc chia sẻ là nó cho phép một ứng dụng có nhiều hoạt động của các Thread khác nhau nằm trong cùng không gian địa chỉ. => nhanh
Kinh tế:
  • cấp phát bộ nhớ và các tài nguyên cho việc tạo các quá trình là rất đắt (chậm). 
  • Vì các Thread chia sẻ tài nguyên của quá trình mà chúng thuộc về nên nó kinh tế hơn việc tạo quá trình và chuyển ngữ cảnh giữa các Thread . 
  • Sử dụng kiến trúc đa xử lý: 
  • các lợi điểm của MultiThread có thể phát huy trong kiến trúc đa xử lý, ở đó mỗi Thread thực thi song song trên một bộ xử lý khác nhau. 
  • Một quá trình đơn Thread chỉ có thể chạy trên một CPU. MultiThread trên một máy nhiều CPU gia tăng tính đồng hành. (GPU)


Multithreading vs. multitasking 
Multithreading đòi hỏi ít tài nguyên hơn multitasking.

In multitasking, các chương trình chạy trên các không gian địa chỉ của chúng và khác nhau giữa các chương trình
đòi hỏi nhiều tài nguyên của hệ thống (cả ram và CPU)
In multithreading các tác vụ có thể chia sẻ cùng không gian địa chỉ
Multithreading cho phép viết các chương trình có hiệu quả cao với sự tận dụng CPU là tối đa bằng cách duy trì thời gian trễ là tối thiểu