http://vietjack.com/java/index.jsp Copyright © vietjack.com Đa luồng Java Java ngơn ngữ chương trình đa luồng (multithreaded), nghĩa phát triển chương trình đa luồng sử dụng Java Một chương trình đa luồng chứa hai nhiều phần mà chạy đồng thời phần xử lý tác vụ khác thời điểm, để sử dụng tốt nguồn có sẵn, đặc biệt máy tính bạn có nhiều CPU Theo định nghĩa, đa nhiệm (multitasking) nhiều tiến trình chia sẻ nguồn xử lý chung ví dụ CPU Đa luồng kế thừa ý tưởng đa nhiệm ứng dụng để bạn chia nhỏ hoạt động riêng biệt bên ứng dụng đơn thành luồng (thread) riêng lẻ Mỗi thread chạy song song OS phân chia thời gian xử lý không ứng dụng khác nhau, mà luồng bên ứng dụng Đa luồng cho bạn khả viết chương trình mà có nhiều hoạt động phát sinh đồng thời Để hiểu sâu khái niệm trình bày chương này, mời bạn tham khảo loạt bài: Ví dụ Thread Java Vòng đời Thread Java Một thread qua giai đoạn khác vòng đời Ví dụ, thread sinh ra, bắt đầu, chạy sau hủy Sơ đồ sau biểu diễn vòng đời đầy đủ thread Các giai đoạn giải thích sau: http://vietjack.com/ Trang chia sẻ học online miễn phí Page http://vietjack.com/java/index.jsp Copyright © vietjack.com New: Một thread bắt đầu vòng đời trạng thái new Nó tồn trạng thái tới chương trình bắt đầu thread Nó xem thread sinh Runnable: Sau thread sinh bắt đầu, thread trở thành runnable Một thread trạng thái xem thực tác vụ Waiting: Đơi khi, thread độ qua trạng thái waiting thread đợi cho thread khác thực tác vụ Một thread chuyển trạng thái runnable thread khác hiệu cho thread đợi để tiếp tục thực thi Timed waiting: Một thread trạng thái runnable vào trạng thái timed waiting khoảng thời gian Một thread trạng thái chuyển trạng thái runnable khoảng thời gian kết thúc kiện đợi xuất Terminated: Một thread trạng thái runnable vào trạng thái terminated hồn thành tác vụ nó chấm dứt Quyền ưu tiên thread Java Mỗi thread Java có quyền ưu tiên mà giúp hệ điều hành xác định thứ tự thread ghi lịch trình Quyền ưu tiên thread Java dãy MIN_PRIORITY (hằng số 1) MAX_PRIORITY (hằng số 10) Theo mặc định, thread cung cấp quyền ưu tiên NORM_ PRIORITY (hằng số 5) Các thread với quyền ưu tiên cao quan trọng với chương trình nên cấp phát thời gian vi xử lý trước thread có quyền ưu tiên thấp Tuy nhiên, quyền ưu tiên thread bảo đảm thứ tự thread thực thi phụ thuộc nhiều vào platform Tạo thread triển khai Runnable Interface Java Nếu class bạn có ý định để thực thi thread, bạn đạt điều triển khai Runnable Interface Bạn cần theo bước sau: http://vietjack.com/ Trang chia sẻ học online miễn phí Page http://vietjack.com/java/index.jsp Copyright © vietjack.com Bước 1: Tại bước này, bạn cần triển khai phương thức run() cung cấp RunnableInterface Phương thức cung cấp điểm vào (entry) cho thread Sau cú pháp đơn giản phương thức run() Java: public void run( ) Bước 2: Tại đây, bạn thuyết minh đối tượng Thread, sử dụng constructor sau Java: Thread(Runnable threadObj, String threadName); Ở đây, threadObj instance lớp mà triển khai Runnable Interface vàthreadName tên cung cấp cho thread Bước Khi đối tượng Thread tạo, bạn bắt đầu gọi phương thức start() Java, mà thực thi triệu hồi tới phương thức run() Sau cú pháp đơn giản phương thức start() Java: void start( ); Ví dụ: Ví dụ sau để tạo thread bắt đầu chạy: class RunnableDemo implements Runnable { private Thread t; private String threadName; RunnableDemo( String name){ threadName = name; System.out.println("Creating " + threadName ); } public void run() { System.out.println("Running " + threadName ); try { for(int i = 4; i > 0; i ) { http://vietjack.com/ Trang chia sẻ học online miễn phí Page http://vietjack.com/java/index.jsp Copyright © vietjack.com System.out.println("Thread: " + threadName + ", " + i); // Let the thread sleep for a while Thread.sleep(50); } } catch (InterruptedException e) { System.out.println("Thread " + threadName + " interrupted."); } System.out.println("Thread " + threadName + " exiting."); } public void start () { System.out.println("Starting " + threadName ); if (t == null) { t = new Thread (this, threadName); t.start (); } } } public class TestThread { public static void main(String args[]) { RunnableDemo R1 = new RunnableDemo( "Thread-1"); R1.start(); RunnableDemo R2 = new RunnableDemo( "Thread-2"); R2.start(); } } http://vietjack.com/ Trang chia sẻ học online miễn phí Page http://vietjack.com/java/index.jsp Copyright © vietjack.com Nó cho kết quả: Creating Thread-1 Starting Thread-1 Creating Thread-2 Starting Thread-2 Running Thread-1 Thread: Thread-1, Running Thread-2 Thread: Thread-2, Thread: Thread-1, Thread: Thread-2, Thread: Thread-1, Thread: Thread-2, Thread: Thread-1, Thread: Thread-2, Thread Thread-1 exiting Thread Thread-2 exiting Tạo Thread kế thừa lớp Thread Java Cách thứ hai để tạo thread kế thừa lớp Thread theo hai bước đơn giản Cách tiếp cận linh động việc xử lý nhiều thread tạo sử dụng phương thức có sẵn lớp Thread Java Bước Bạn cần override phương thức run() có sẵn lớp Thread Phương thức cung cấp điểm entry cho thread Sau cú pháp đơn giản phương thức run() Java: public void run( ) Bước Khi đối tượng Thread tạo, bạn bắt đầu gọi phương thức start() Java, mà thực thi triệu hồi tới phương thức run() Sau cú pháp đơn giản phương thức start() Java: http://vietjack.com/ Trang chia sẻ học online miễn phí Page http://vietjack.com/java/index.jsp Copyright © vietjack.com void start( ); Ví dụ: Đây ví dụ viết lại để kế thừa lớp Thread: class ThreadDemo extends Thread { private Thread t; private String threadName; ThreadDemo( String name){ threadName = name; System.out.println("Creating " + threadName ); } public void run() { System.out.println("Running " + threadName ); try { for(int i = 4; i > 0; i ) { System.out.println("Thread: " + threadName + ", " + i); // Let the thread sleep for a while Thread.sleep(50); } } catch (InterruptedException e) { System.out.println("Thread " + threadName + " interrupted."); } System.out.println("Thread " + threadName + " exiting."); } public void start () { System.out.println("Starting " + threadName ); if (t == null) { t = new Thread (this, threadName); t.start (); http://vietjack.com/ Trang chia sẻ học online miễn phí Page http://vietjack.com/java/index.jsp Copyright © vietjack.com } } } public class TestThread { public static void main(String args[]) { ThreadDemo T1 = new ThreadDemo( "Thread-1"); T1.start(); ThreadDemo T2 = new ThreadDemo( "Thread-2"); T2.start(); } } Nó cho kết sau: Creating Thread-1 Starting Thread-1 Creating Thread-2 Starting Thread-2 Running Thread-1 Thread: Thread-1, Running Thread-2 Thread: Thread-2, Thread: Thread-1, Thread: Thread-2, Thread: Thread-1, Thread: Thread-2, Thread: Thread-1, Thread: Thread-2, Thread Thread-1 exiting Thread Thread-2 exiting http://vietjack.com/ Trang chia sẻ học online miễn phí Page http://vietjack.com/java/index.jsp Copyright © vietjack.com Các phương thức lớp Thread Java Bảng liệt kê phương thức quan trọng có sẵn lớp Thread Java: STT Phương thức Miêu tả public void start() Bắt đầu thread path riêng rẽ, sau triệu hồi phương thức run() đối tượng Thread public void run() Nếu đối tượng Thread thuyết minh sử dụng đối tượng Runnable, phương thức run() triệu hồi đối tượng Runnable public final void setName(String name) Thay đổi tên đối tượng Thread Cũng có phương thức getName() để thu nhận tên public final void setPriority(int priority) Thiết lập quyền ưu tiên đối tượng Thread Giá trị có nằm khoảng từ tới 10 public final void setDaemon(boolean on) Một tham số true chứng tỏ Thread Daemon thread public final void join(long millisec) Thread triệu hồi phương thức thread thứ hai, làm cho Thread block tới thread thứ hai kết thúc sau số lượng mili giây xác định public void interrupt() Ngắt thread này, làm cho tiếp tục thực thi bị block lý http://vietjack.com/ Trang chia sẻ học online miễn phí Page http://vietjack.com/java/index.jsp Copyright © vietjack.com public final boolean isAlive() Trả true thread alive, mà thời gian sau thread bắt đầu trước run tới kết thúc Các phương thức triệu hồi đối tượng Thread cụ thể Các phương thức sau lớp Thread static Triệu hồi phương thức thực hoạt động thread chạy STT Phương thức Miêu tả public static void yield() Làm cho thread chạy chuyển tới thread khác có quyền ưu tiên mà đợi để ghi lịch trình public static void sleep(long millisec) Làm cho thread chạy block số lượng mili giây xác định public static boolean holdsLock(Object x) Trả true thread giữ lock Object cho public static Thread currentThread() Trả tham chiếu tới thread chạy tại, mà thread mà triệu hồi phương thức public static void dumpStack() In stack trace cho thread chạy Nó hữu ích debugging ứng dụng đa luồng http://vietjack.com/ Trang chia sẻ học online miễn phí Page http://vietjack.com/java/index.jsp Copyright © vietjack.com Ví dụ: Chương trình ThreadClassDemo sau minh họa số phương thức lớp Thread Bạn để ý lớp DisplayMessage triển khai Runnable: // File Name : DisplayMessage.java // Create a thread to implement Runnable public class DisplayMessage implements Runnable { private String message; public DisplayMessage(String message) { this.message = message; } public void run() { while(true) { System.out.println(message); } } } Sau lớp khác mà kế thừa lớp Thread: // File Name : GuessANumber.java // Create a thread to extentd Thread public class GuessANumber extends Thread { private int number; public GuessANumber(int number) { this.number = number; } public void run() http://vietjack.com/ Trang chia sẻ học online miễn phí Page 10 http://vietjack.com/java/index.jsp Copyright © vietjack.com { int counter = 0; int guess = 0; { guess = (int) (Math.random() * 100 + 1); System.out.println(this.getName() + " guesses " + guess); counter++; }while(guess != number); System.out.println("** Correct! " + this.getName() + " in " + counter + " guesses.**"); } } Dưới chương trình mà sử dụng lớp định nghĩa trên: // File Name : ThreadClassDemo.java public class ThreadClassDemo { public static void main(String [] args) { Runnable hello = new DisplayMessage("Hello"); Thread thread1 = new Thread(hello); thread1.setDaemon(true); thread1.setName("hello"); System.out.println("Starting hello thread "); thread1.start(); Runnable bye = new DisplayMessage("Goodbye"); Thread thread2 = new Thread(bye); thread2.setPriority(Thread.MIN_PRIORITY); thread2.setDaemon(true); System.out.println("Starting goodbye thread "); http://vietjack.com/ Trang chia sẻ học online miễn phí Page 11 http://vietjack.com/java/index.jsp Copyright © vietjack.com thread2.start(); System.out.println("Starting thread3 "); Thread thread3 = new GuessANumber(27); thread3.start(); try { thread3.join(); }catch(InterruptedException e) { System.out.println("Thread interrupted."); } System.out.println("Starting thread4 "); Thread thread4 = new GuessANumber(75); thread4.start(); System.out.println("main() is ending "); } } Nó cho kết sau Bạn chạy thử ví dụ nhiều lần thấy cho kết khác lần chạy Starting hello thread Starting goodbye thread Hello Hello Hello Hello Hello Hello Goodbye Goodbye Goodbye http://vietjack.com/ Trang chia sẻ học online miễn phí Page 12 http://vietjack.com/java/index.jsp Copyright © vietjack.com Goodbye Goodbye Một số khái niệm Đa luồng chủ yếu Java Trong lập trình đa luồng Java, bạn thấy tiện lợi bạn biết khái niệm sau: Thread Synchronization Java InterThread Communication Java Thread deadlock Java Thread Control Java Để hiểu sâu khái niệm trình bày chương này, mời bạn tham khảo loạt bài: Ví dụ Thread Java http://vietjack.com/ Trang chia sẻ học online miễn phí Page 13 ... Thread- 1, Running Thread- 2 Thread: Thread- 2, Thread: Thread- 1, Thread: Thread- 2, Thread: Thread- 1, Thread: Thread- 2, Thread: Thread- 1, Thread: Thread- 2, Thread Thread-1 exiting Thread Thread-2... Starting Thread- 1 Creating Thread- 2 Starting Thread- 2 Running Thread- 1 Thread: Thread- 1, Running Thread- 2 Thread: Thread- 2, Thread: Thread- 1, Thread: Thread- 2, Thread: Thread- 1, Thread: Thread- 2, Thread: ... "Thread- 1"); T1.start(); ThreadDemo T2 = new ThreadDemo( "Thread- 2"); T2.start(); } } Nó cho kết sau: Creating Thread- 1 Starting Thread- 1 Creating Thread- 2 Starting Thread- 2 Running Thread- 1 Thread: