LẬP TRÌNH ĐA TUYẾN Giới Thiệu • Hệ điều hành đa nhiệm cổ điển: – Đơn vị cơ bản sử dụng CPU là quá trình (process). – Quá trình là đoạn chương trình độc lập đã được nạp vào bộ nhớ. – Mỗi quá trình thi hành một ứng dụng riêng. – Mỗi quá trình có một không gian địa chỉ và một không gian trạng thái riêng.
– Các quá trình liên lạc với nhau thông qua HĐH, tập tin, mạng. Giới Thiệu • Tuyến là mạch thi hành độc lập của một tác vụ trong chương trình. • Một chương trình có nhiều tuyến thực hiện cùng lúc gọi là đa tuyến. 3 Giới Thiệu • Hệ điều hành đa nhiệm hiện đại, hỗ trợ luồng: – Đơn vị cơ bản sử dụng CPU là luồng (thread).
– Luồng một đoạn các câu lệnh được thi hành. – Mỗi quá trình có một không gian địa chỉ và nhiều luồng điều khiển. – Mỗi luồng có bộ đếm chương trình, trạng thái các thanh ghi và ngăn xếp riêng. – Luồng của một quá trình có thể chia sẻ nhau không gian địa chỉ : Biến toàn cục, tập tin, chương trình con, hiệu báo,.
– Luồng chia sẻ thời gian sử dụng CPU => Luồng cũng có các trạng thái: Sẵn sàng (ready), Đang chạy (running), Nghẽn(Block) như quá trình. – Luồng cung cấp cơ chế tính toán song song trong các ứng dụng. Chương trình đơn tuyến class ABC { …. public void main(.
end } } 5 Đa tuyến • Là khả năng làm việc với nhiều tuyến • Đa tuyến chuyên sử dụng cho việc thực thi nhiều công việc đồng thời • Đa tuyến giảm thời gian rỗi của hệ thống đến mức thấp nhất. A Multithreaded Program Main Thread start start start Thread A Thread B Thread C 7 Các thread có thể chuyển đổi dữ liệu với nhau Cơ Chế Thi Hành Client Thread Runnable new(runnable) Init a new thread start() run() Runs in a new doTheStuff() control flow Returns immediately Thread is finished Ứng Dụng Multithreading Printing Thread Editing Thread 9 Multithreaded Server Client 1 Process Server Process Server Threads Internet Client 2 Process 10 Web/Internet Applications PC client Internet Server Local Area Network PD A 11 Lập trình đa tuyến với Java • Cách thực hiện – Sử dụng lớp «interface» Runnable 1 java.Thread +run() public class Thread extends Object { … } Thread – Sử dụng giao diện +currentThread() : Thread +isInterrupted() : bool java.Runnable +sleep(in millis : long) : long +yield() public interface Runnable { +isAlive() +join() public void run(); // work +interrupt() +start() +stop() thread } Lớp java.Thread • Luồng trong java là một đối tượng của lớp java.Thread • Một chương trình cài đặt luồng bằng cách tạo ra các lớp con của lớp Thread. • Lớp Thread có 3 phương thức cơ bản: – public static synchronized void start() : • Chuẩn bị mọi thứ cần thiết để thực hiện luồng. – public void run(): • Chứa mã lệnh thực hiện công việc thực sự của luồng.
– public void stop() : kết thúc một luồng. – Luồng kết thúc khi: – Hoặc tất cả các lệnh trong run() đã được thực thi. – Hoặc phương thức stop() của luồng được gọi. Tạo và quản lý tuyến • Khi chương trình Java thực thi hàm main() tức là tuyến main được thực thi.
Tuyến này được tạo ra một cách tự động. tại đây : - Các tuyến con sẽ được tạo ra từ đó - Nó là tuyến cuối cùng kết thúc việc thực hiện. Trong chốc lát tuyến chính ngừng thực thi, chương trình bị chấm dứt • Tuyến có thể được tạo ra bằng 2 cách: – Dẫn xuất từ lớp Thread – Dẫn xuất từ Runnable. Tạo Luông Công Việc java.Runnable TaskClass // Client class public class Client {.
// Custom task class public void someMethod() { public class TaskClass implements Runnable {. // Create an instance of TaskClass public TaskClass(.) { TaskClass task = new TaskClass(. } // Create a thread Thread thread = new Thread(task); // Implement the run method in Runnable public void run() { // Start a thread // Tell system how to run custom thread thread. } } 15 Tạo thread sử dụng lớp Thread • Cài đặt lớp kế thừa từ lớp Thread và override phương thức run() class MyThread extends Thread { public void run() { // thread body of execution } } • Tạo thread: MyThread thr1 = new MyThread(); • Thi hành thread: thr1.println( getName() + " have sleep time: " + sleepTime); } 18 Ví dụ về đa tuyến (tt) // method run is the code to be executed by new thread public void run(){ try{ System.start(); //start and ready to run thread2.start(); //start and ready to run thread3.start(); //start and ready to run System.println( "Threads started, main ends\n" ); } } 20 Ví dụ về đa tuyến (tt) thread1will sleep: 1438 thread2will sleep: 3221 thread1will sleep: 970 thread3will sleep: 1813 thread2will sleep: 950 thread1starts to sleep Theads started.
Thread main finised thread3will sleep: 2564 thread3starts to sleep thread1starts to sleep thread2starts to sleep Theads started. Thread main thread1done sleeping finised thread3done sleeping thread2starts to sleep thread2done sleeping thread3starts to sleep BUILD SUCCESSFUL (total time: 4 seconds) thread2done sleeping thread1done sleeping thread3done sleeping 21 Tạo thread sử dụng Runnable class MyThread implements Runnable {. public void run() { // thread body of execution } } • Tạo đối tượng: MyThread myObject = new MyThread(); • Tạo thread từ đối tượng: Thread thr1 = new Thread( myObject ); • Thi hành thread: thr1.println(" this thread is running. "); } } // end class MyThread class ThreadEx2 { public static void main(String [] args ) { Thread t = new Thread(new MyThread()); // due to implementing the Runnable interface // I can call start(), and this will call run().start(); } // end main() } // end class ThreadEx2 23 Threads – Thread States • Các trạng thái của thread: – New – thread được tạo ra trong bộ nhớ – Runnable – thread có thể được thi hành – Running – thread đang thi hành – Blocked – thread đang bị treo (I/O, etc.) – Dead – thread kết thúc • Việc chuyển đổi trạng thái thread thực hiện bỡi: – Thi hành các phương thức trong lớp Thread • new(), start(), yield(), sleep(), wait(), notify()… – Các sự kiện bên ngoài • Scheduler, I/O, returning from run()… Vòng Đời Của Thread new start notify, notifyAll, new runnable IO complete, sleep expired, yield, scheduler join complete time slice running blocked IO, sleep, terminate wait, join dead A thread’s life cycle Alive Blocked Running wait() Wait for Not New notify notify() / interrupted notifyAll() start() join() Wait for interrupt() target Target finish sleep() Interrupted Sleeping Dead Time out interrupt() run() returns Lưu Ý – Thread chỉ được thi hành sau khi gọi phương thức start() – Runnable là giao tiếp • Có thể hỗ trợ đa kế thừa • Thường dùng khi cài đặt giao diện GUI Ví Dụ • Viết chương trình thi hành song song 3 thread 28 Ví Dụ class A extends Thread { public void run() { for(int i=1;i<=5;i++) { System.start(); } } 30 Run 1 java ThreadTest From ThreadA: i= 1 From ThreadA: i= 2 From ThreadA: i= 3 From ThreadA: i= 4 From ThreadA: i= 5 Exit from A From ThreadC: k= 1 From ThreadC: k= 2 From ThreadC: k= 3 From ThreadC: k= 4 From ThreadC: k= 5 Exit from C From ThreadB: j= 1 From ThreadB: j= 2 From ThreadB: j= 3 From ThreadB: j= 4 From ThreadB: j= 5 Exit from B Run2 java ThreadTest From ThreadA: i= 1 From ThreadA: i= 2 From ThreadA: i= 3 From ThreadA: i= 4 From ThreadA: i= 5 From ThreadC: k= 1 From ThreadC: k= 2 From ThreadC: k= 3 From ThreadC: k= 4 From ThreadC: k= 5 Exit from C From ThreadB: j= 1 From ThreadB: j= 2 From ThreadB: j= 3 From ThreadB: j= 4 From ThreadB: j= 5 Exit from B Exit from A Daemon Threads • Các lọai thread trong Java – User – Daemon • Cài đặt các dịch vụ • Chạy ngầm bên dưới hệ thống • Thi hành phương thức setDaemon() trước khi thi hành start() • Chương trình kết thúc khi: 1.
Tất cả thread hoàn tất. Daemon threads bị kết thúc bỡi JVM 3. Chương trình chính kết thúc Độ Ưu Tiên • Trong Java, mỗi thread được gán 1 giá trị để chỉ mức độ ưu tiên của thread. Khi thread được tạo ra có độ ưu tiên mặc định (NORM_PRIORITY) sẽ được thi hành theo quy tắc FCFS.
– Sử dụng phương thức setPriority() để thay đổi độ ưu tiên của thread: • ThreadName.MAX_PRIORITY); threadB.MIN_PRIORITY); System.println("End of main thread"); } } Threads – Scheduling • Bộ lập lịch – Xác định thread nào sẽ thi hành – Có thể thực hiện dựa trên độ ưu tiên – Là một phần của HĐH hoặc Java Virtual Machine (JVM) • Kiểu lập lịch – Nonpreemptive (cooperative) scheduling – Preemptive scheduling Non-preemptive Scheduling • Thread thi hành cho đến khi – Hoàn tất công việc – Phải chờ sự kiện bên ngoài (IO,…) – Thread chủ động kết thúc thi hành (gọi phương thức yield hoặc sleep) Preemptive Scheduling • Threads thi hành cho đến khi – Tương tự non-preemptive scheduling – Preempted bỡi bộ lập lịch Thread Scheduling • Ví dụ • Tạo lớp kế thừa Thread • Sử dụng phương thức sleep() – Công việc • Tạo 4 thread chạy song sọng, mỗi thread sẽ tạm ngưng thi hành một khoảng thời gian ngẫu nhiên • Sau khi kết thúc sleeping sẽ in ra tên thread.java 2 // Show multiple threads printing at different intervals. 3 4 public class ThreadTester { 5 public static void main( String args[] ) 6 { 7 PrintThread thread1, thread2, thread3, thread4; 8 9 thread1 = new PrintThread( "thread1" ); 10 thread2 = new PrintThread( "thread2" ); 11 thread3 = new PrintThread( "thread3" ); 12 thread4 = new PrintThread( "thread4" ); 13 main kết thúc khi thread cuối cùng kết thúc.println( "Name: " + getName() + 38 Công việc của "; thread sleep: " + sleepTime ); 39 } 40 Sleep có thể ném ra biệt lệ 41 // execute the thread 42 public void run() 43 { 44 // put thread to sleep for a random interval 45 try { 46 System.toString() ); 51 } 52 53 // print thread name 54 System.println( getName() + " done sleeping" ); 55 } 56 } Truy Cập Tài Nguyên Dùng Chung • Các ứng dụng truy cập vào tài nguyên dùng chung cần có cơ chế phối hợp để tránh đụng độ.