1. Trang chủ
  2. » Giáo Dục - Đào Tạo

Session07 threads tien trinh

11 45 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 11
Dung lượng 1,18 MB

Nội dung

2/23/2018 Nội dung CÔNG NGHỆ JAVA CH7 THREADS – TIẾN TRÌNH Giảng viên: ThS Lê Nhật Tùng www.lenhattung.com Luồng đa luồng • Luồng- thread: Một dòng lệnh mà CPU phải thực thi • Các hệ điều hành cho phép nhiều luồng thực thi đồng thời Chúng ta quen với việc mở nhiều ứng dụng lần làm việc với máy tính  Nhiều ứng dụng nạp • Như – Một luồng chuỗi lệnh nằm nhớ ( chương trình nạp) – application thơng thường thực thi luồng – Trong application có nhiều luồng Thí dụ chuyển động 10 đối tượng hành trò chơi 10 luồng 1- Luồng đa luồng 2- Luồng Java 3- Trạng thái luồng 4- Lập trình luồng Java 5- Độ ưu tiên luồng 6- Đồng luồng 7- Deadlock 8- Cơ chế Chờ-nhận biết 9- Tóm tắt Kỹ thuật đa luồng • Với máy có m CPU chạy m luồng  Mỗi CPU chạy luồng  Hiệu • Với máy có m CPU chạy n luồng với n>> m Mỗi CPU chạy n/m luồng • Với CPU chạy đồng thời k luồng với k>1 Các luồng quản lý hàng đợi, luồng cấp phát thời gian mà CPU thực thi ti (cơ chế time-slicing – phân chia tài nguyên thời gian) Luồng đỉnh hàng đợi lấy để thực thi trước, sau ti thời gian mình, luồng đưa vào cuối hàng đợi CPU lấy luồng • Với máy có CPU mà lại chạy k luồng  Hiệu suất chương trình 2/23/2018 Lợi ích đa luồng Luồng Java • Tăng hiệu suất sử dụng CPU: Phần lớn thời gian thực thi ứng dụng chờ đợi nhập liệu từ user  hiệu suất sử dụng CPU chưa hiệu qủa • Tạo đồng đối tượng: Thí dụ trò chơi, nhân vật chuyển động Trong trang Web, tạo đồng thời đường diềm (marquee) tiêu đề động (banner, chữ,ảnh chạy), vừa hiển thị đồng hồ, vừa phát nhạc, vừa chơi game, vừa hoạt ảnh (animated images),…  Trang Web thật bắt mắt (eyecatching) quyến rũ (captivating) • Quản lý thời gian ứng dụng thi online, thời gian chơi trò chơi Trạng thái luồng Trạng thái luồng Sinh (Born) new Thread() Hết thời gian ngủ Sẵn sàng ( Ready ) notify() notify() start() Đang chờ ( Waiting ) Ngủ lúc ( Sleeping ) wait() Bị tạm hỗn ( Suspended ) run() Bị khóa ( Blocked ) wait() sleep() Đang chạy ( Running ) stop() hay chạy xong Hành vi để buộc luồng chuyển trạng thái  Main thread - luồng : luồng chứa luồng khác Đây luồng cho Java Application hành (mức toàn application)  Child thread - luồng : luồng tạo từ luồng khác  Khi application thực thi, main thread chạy, gặp phát biểu phát sinh luồng con, luồng khởi tạo Vào thời điểm luồng kết thúc, application kết thúc  Java cung cấp lớp Thread mơ tả luồng gói java.lang Đã chết ( Dead ) chờ biến cố xuất/nhập • Một luồng sau sinh (born) không chạy mà sẵn sàng (ready) chạy Chỉ phương thức start() gọi luồng thực thi (chạy code phương thức run()) • Luồng thực thi bị tạm ngưng phương thức sleep() thời khoảng lại ready sau đáo hạn thời gian Luồng ngủ không sử dụng tài nguyên CPU • Khi nhiều luồng thực thi, có luồng giữ tài ngun mà khơng nhả làm cho luồng khác không dùng tài ngun (đói tài ngun) Để tránh tình này, Java cung cấp chế Wait-Notify(đợi-nhận biết) chế trình bầy mục sau Phương thức wait() giúp đưa luồng vào trạng thái chờ 2/23/2018 Trạng thái luồng • Khi luồng bị tạm ngưng hay bị treo, luồng rơi vào trạng thái tạm hoãn (suspended) Phương thức suspend()- version cũ/ wait() Java dùng cho mục đích • Khi suspended thread mang thực thi tiếp, trạng thái luồng resumed Phương thức resume() – version cũ/ notify() Java dùng cho mục đích • Khi luồng chờ biến cố xuất/nhập liệu Luồng rơi vào trạng thái blocked • Khi luồng thực thi xong phương thức run() hay gặp phương thức stop(), ta nói luồng chết (dead) Tham khảo lớp Thread Lập trình luồng Java • Cách 1: Xây dựng lớp lớp java.lang.Thread, override hành vi run() để phù hợp với mục đích tốn • Cách 2: Xây dựng lớp có thực interface Runnable – Khơng cần import java.lang gói – java.lang.Thread lớp Java xây dựng sẵn thực interface Runnable – Interface java.lang.Runnable có method run() – Tham khảo thêm gói java.lange Tạo luồng lớp lớp Thread class MyThread extends Thread{ // liệu + hành vi lớp public void run(){ // thực code phụ thuộc toán } } 2/23/2018 Tạo luồng với interface Runnable Khởi tạo thực thi luồng class MyThread implements Runnable{ // liệu + hành vi lớp public void run(){ // thực code phụ thuộc toán } } MyThread t = new MyThread(); // tạo luồng t.start(); // thị cho luồng thực thi Thread Constructors Hai loại luồng Thread () Thread (Runnable target) Thread (Runnable target, String Name) Thread (String Name) Thread (ThreadGroup group, Runnable target) Thread (ThreadGroup group, Runnable target, String Name) Thread (ThreadGroup group, Runnable target, String Name, long stacksize) • Thread (ThreadGroup group, String Name) • Luồng Daemon: luồng hệ thống, chạy mức (background- chạy ngầm), luồng cung cấp dịch vụ cho luồng khác Các trình JVM tồn luồng daemon tồn JVM có luồng daemon luồng “garbage collection” • Luồng user tạo • • • • • • • • target : luồng cha • name: tên gọi luồng tạo Hành vi start() tự động gọi hành vi run() 2/23/2018 Methods thông dụng lớp Thread Method Methods thông dụng lớp Thread Mục đích static int enumerate (Thread Sao chép luồng tích cực vào [] t) mảng từ nhóm luồng nhóm chúng final String getName() Lấy tên luồng final boolean isAlive() Kiểm tra luồng sống hay khơng? Method Mục đích static void sleep (long Trì hỗn luồng thời gian milisec) void start() thực thi luồng final void setName( String Đặt tên cho luồng NewName) static int activeCount() Đếm số luồng tích cực final void join () throws Chờ luồng chết interruptedException static void yield() Tạm dừng luồng hành để luồng khác tiếp tục thực thi public final isDaemon() boolean Kiểm tra xem luồng có phải luồng daemon void setDaemon(boolean on) on=true : luồng daemon on=false : luồng user Minh họa tạo luồng với lớp Thread Minh họa tạo luồng với lớp interface Runnable // Thread1.java – Minh họa tạo luồng với lớp Thread class Thread1 extends Thread { public void Create() // tạo luồng luồng cha hành { Thread t = new Thread (this); t.start(); } public void run() // override hành vi run() { System.out.println("This is child thread."); } public static void main (String args[]) { System.out.println("This is main thread."); Thread1 t= new Thread1(); Kết qủa: t.Create(); // tạo luồng This is main thread } This is child thread Pres any key to continue } class Thread2 implements Runnable interface Runable, phải khai báo đối tượng { public void Create() Thread gọi hành vi { Thread t = new Thread(this); start() để hành vi gọi run() t.start(); } public void run() // implement the run () method { System.out.println("This is child thread."); } public static void main (String args[]) { System.out.println("This is main thread."); Thread2 t= new Thread2(); t.Create(); Kết qủa: } This is main thread } This is child thread Khi xây dựng luồng Pres any key to continue 2/23/2018 Minh họa số methods Thread class Thread3 implements Runnable // Thread3.java { Thread t1,t2; Thread3() { t1= new Thread(this); t1.start(); // t1 is an user-defined thread t2= new Thread(this); t2.setDaemon(true); // t2 is a daemon thread } public void run() { int n= Thread.activeCount(); // Đếm số luồng tích cực JVM System.out.println("Number of active threads:" + n); String t1Name = t1.getName(); // lấy tên luồng String t2Name = t2.getName(); System.out.println("Name of t1 thread:" + t1Name); System.out.println("Name of t2 thread:" + t2Name); System.out.println("Is t1 thread a daemon? :" + t1.isDaemon()); System.out.println("Is t2 thread a daemon? :" + t2.isDaemon()); System.out.println("Is t1 thread alive? :" + t1.isAlive()); System.out.println("Is t2 thread alive? :" + t2.isAlive()); } public static void main (String args[]) { System.out.println("This is main thread."); Thread3 t= new Thread3(); } mặc định luồng Thread-n, với n số thứ Tên } Kết qủa luồng tích cực : luồng gom rác, luồng mẹ luồng t1,t2 Kết This is main thread Number of active threads:4 Name of t1 thread:Thread-1 Name of t2 thread:Thread-2 Is t1 thread a daemon? :false Is t2 thread a daemon? :true Is t1 thread alive? :true Is t2 thread alive? :false Press any key to continue tự luồng tạo Độ ưu tiên luồng • Các luồng chia sẻ thời gian CPU  Luồng cuối hàng đợi lâu CPU thực thi  Có nhu cầu thay đổi độ ưu tiên luồng Java cung cấp mô tả độ ưu tiên luồng (các độ ưu tiên khác dùng số nguyên từ 10) • NORM_PRIORITY : mang trị • MAX_PRIORITY : mang trị 10 • MIN_PRIORITY : mang trị • Độ ưu tiên mặc định luồng NORMAL_PRIORITY Luồng có độ ưu tiên với luồng cha (do đặc điểm thừa kế) Minh họa trạng thai luồng class Thread4 extends Thread// // Thread4.java { Thread t; Thread4() { t= new Thread(this); System.out.println("t thread is born and ready."); t.start(); } public void run() { try { System.out.println("t thread is running."); t.sleep(5000); System.out.println("t is awaked and running again after secs."); Dòng xuất sau giây } so với dòng trước catch( InterruptedException e) { System.out.println("thread is interrupted!"); } t thread is born and ready } t thread is running public static void main (String args[]) t is awaked and running again after secs { new Thread4(); Press any key to continue } } Thao tác với độ ưu tiên luồng • final void setPriority( int newPriority) • final int getPriority() Như vậy, điều kiện để luồng khơng thực thi: • Luồng khơng có độ ưu tiên cao để dành lấy thời gian CPU • Luồng bị cưỡng ngủ hành vi sleep() • Luồng bị chờ hành vi wait() • Luồng bị tường minh nhận hành vi yield() • Luồng bị khóa chờ I/O 2/23/2018 Minh họa độ ưu tiên luồng class Thread5 extends Thread// Thread4.java { public void run() { Thread Child = new Thread(this); Child.setName("Child thread"); System.out.println("Name of current thread:" + Thread.currentThread().getName()); System.out.println("Piority of current thread:" + Thread.currentThread().getPriority()); System.out.println("Name of child:" + Name of current thread:Parent thread Child.getName()); Piority of current thread:5 System.out.println("Priority of child:" + Name of child:Child thread Child.getPriority()); Priority of child:5 } Press any key to continue public static void main (String args[]) { Thread5 t = new Thread5(); Nếu main(), thêm dòng t.start(); t.setPriority (8); trước dòng t.start(); t.setName("Parent thread"); ta có kết qủa thay } } Kỹ thuật đồng hóa • • • Tạo đối tượng quản lý đồng thao tác liệu luồng cách thực thi hộ tác vụ luồng lần cho luồng từ khóa synchronized Mọi đối tượng luồng đối tượng quản lý quan sát (MONITOR) cách cho đối tượng luồng có liệu đối tượng monitor thay phải làm tác vụ nhờ đối tượng monitor làm hộ biến boolean để nhận biết có luồng thực thi  Luồng chiếu cố gọi luồng có monitor Đồng luồng • Tình huống: Có hai luồng t1, t2 truy xuất đối tượng liệu biến m t1 muốn đọc biến m t2 muốn ghi biến m  liệu mà t1 đọc khơng qn  Nếu t2 ghi m trước t1 đọc sau t1 đọc liệu quán thời điểm  Cần có chế phép luồng truy xuất liệu chung (shared data) thời điểm •  Kỹ thuật gọi “ĐỒNG BỘ HÓA – SYNCHRONIZATION” Minh họa đồng luồng MONITOR Chương trình sau xuất số 10,11, 12 hình, số luồng thực thi // Monitor1.java – Lớp làm nhiệm vụ xuất hộ số num class Monitor1 { synchronized void Display (int num) { System.out.println("Output " + num + " - done."); try { Thread.sleep(500); // current thread sleep 1/2 sec } catch (InterruptedException e) { System.out.println ("Thread is interrupted!"); } } } Từ khóa synchronized khai báo có quản lý việc đồng luồng 2/23/2018 Minh họa đồng luồng MONITOR Minh họa đồng luồng MONITOR class OutNum implements Runnable // luồng { Monitor1 monitor; // Luồng có liệu monitor int number; // liệu cần xuất Thread t; // hành vi xuất n với Monitor1 có tên moni OutNum(Monitor1 moni, int n ) { monitor= moni; number = n; t = new Thread(this); t.start(); } // luồng chạy, số number xuất monitor public void run() { monitor.Display(number); } } class Synchro // lớp chương trình luồng có trị { public static void main (String args[]) khác 10,11, 12 { Monitor1 monitor = new Monitor1(); có chung int num = 10; monitor OutNum Obj1 = new OutNum(monitor,num++); Ba luồng OutNum Obj2 = new OutNum(monitor,num++); OutNum Obj3 = new OutNum(monitor,num++); // wait for threads to end try Output 10 - done { Obj1.t.join(); Output 11 - done Obj2.t.join(); Output 12 - done Obj3.t.join(); Press any key to continue } catch(InterruptedException e) { System.out.println ("Thread was interrupted!"); } } } Kỹ thuật đồng luồng theo khối Kỹ thuật đồng luồng theo khối • • • Đồng khối tác vụ Người lập trình không muốn dùng synchronized method để đồng truy xuất đến đối tượng Các lớp cung cấp thư viện hay “một đó” cung cấp – lớp xây dựngnên thêm từ khóa synchonized vào method • Cú pháp đồng khối synchronized (Object) { } • Buộc phải có { } dù có phát biểu 2/23/2018 Minh họa đồng khối Chương trình sau viết lại chương trình trước, bỏ qua từ khóa synchronized lớp Monitor1 ( gọi lớp Monitor2) class Monitor2 // Monitor2.java { void Display (int num) { System.out.println("Output " + num + " - done."); try { Thread.sleep(500); // current thread sleap 1/2 sec } catch (InterruptedException e) { System.out.println ("Thread is interrupted!"); } } } Minh họa đồng khối class Synchro { public static void main (String args[]) { Monitor2 monitor = new Monitor2(); int num = 10; OutNum Obj1 = new OutNum(monitor,num++); OutNum Obj2 = new OutNum(monitor,num++); OutNum Obj3 = new OutNum(monitor,num++); // wait for threads to end try { Obj1.t.join(); Obj2.t.join(); Obj3.t.join(); } catch(InterruptedException e) { System.out.println ("Thread was interrupted!"); } } } Minh họa đồng khối Deadlock class OutNum implements Runnable { Monitor2 monitor; int number; Thread t; OutNum(Monitor2 moni, int n ) { monitor= moni; number = n; t = new Thread(this); t.start(); } public void run() { synchronized (monitor) { monitor.Display(number); } } } • Deadlock – tình bế tắc, đóng băng- xẩy luồng chờ tài nguyên (monitor) hình thành chu trình Deadlock xẩy 2/23/2018 Cơ chế chờ- nhận biết Cơ chế wait-notify • Java cung cấp sẵn chế giao tiếp liên qúa trình (inter-process mechanism) để luồng gọi (yêu cầu nhau) sử dụng final methods lớp Object: wait() , notify() , notifyAll() Như lớp sử dụng chúng phương thức gọi synchronized methods • Phương thức wait() : Luồng nhả monitor để vào trạng thái sleep luồng khác vào monitor gọi phương thức notify • Phương thức notify() : Luồng thức dậy (wake up) nhận biết (notify) luồng thứ gọi wait() • Phương thức notifyAll() : Đánh thức tất luồng ngủ để chúng biết luồng hành gọi phương thức wait() Khi tất luồng ngủ thức dậy, luồng có ưu tiên cao nắm giữ monitor thực thi Chú ý phương thức wait Chú ý phương thức notify • Luồng gọi phương thức wait() nhả CPU, không dùng CPU • Luồng gọi phương thức wait() nhả monitor, khơng khóa (lock) monitor • Luồng gọi phương thức wait() đưa vào danh sách hàng đợi monitor (monitor waiting pool) • Một luồng ngủ đưa khỏi monitor waiting pool vào trạng thái ready • Luồng vừa thức giấc (notify) phải giành lại monitor khóa monitor lại khơng cho luồng khác chiếm để luồng thực thi 2/23/2018 Chú ý phương thức notifyAll • Luồng thực thi cảnh báo cho tất luồng ngủ “Tôi ngủ đây, bạn dậy để làm việc” • Luồng đầu danh sách monitor waiting pool vào trạng thái ready Tóm tắt • Hiện thực luồng cách: • Hiện thực lớp lớp Thread, override phương thức run() lớp • Khai báo lớp mà ta xây dựng implement interface Runnable định nghĩa phương thức run() • Mỗi java thread có độ ưu tiên từ (MIN) đến 10 (MAX) với trị mặc định JVM không thay đổi độ ưu tiên luồng • Có contructor lớp Thread constructor thường dùng: Thread() Thread(String TênLuồng), Thread(ĐốiTượngChứa) • Các phương thức Thread.suspend(), Thread.resume(), Thread.stop() khơng dùng kể từ Java • Luồng daemon luồng chạy ngầm nhằm cung cấp dịch vụ cho luồng khác Nếu muốn luồng daemon, dùng public final void setDeamon (boolean) kiểm tra luồng có daemon hay không, dùng public final boolean isDaemon() Tóm tắt • Luồng biện pháp chia cơng việc thành đơn vị cụ thể (concrete) nên dùng để thay vòng lặp • Lập trình đa luồng làm tăng hiệu suất CPU hệ thống “bận rộn” Tuy nhiên hiệu suất ứng dụng lại bị giảm kể (chậm ba bốn lần tác vụ đồng hóa), qúa trình biên dịch chậm trình biên dịch phải tính tốn chế quản lý luồng Do caùc ứng dụng đòi hỏi yếu tố hiệu suất thời gian quan trọng, nên tránh sử dụng kỹ thuật đồng hóa  Nhiều lập trình viên khơng thích lập trình đa luồng mà dùng lập trình lập trình đơn luồng để tăng hiệu suất ứng dụng • Java cung cấp kỹ thuật lập trình đa luồng lớp Thread interface Runnable • Khi ứng dụng Java thực thi, có luồng chạy luồng (main thread) Luồng quan trọng (1) Đây luồng sinh luồng con, (2) Quản lý việc kết thúc ứng dụng luồng main kết thúc tất luồng kết thúc Tóm tắt • Dữ liệu bị quán(hư hỏng) có luồng truy xuất liệu thời điểm • Đồng 1q trình bảo đảm tài nguyên (dữ liệu, file,…) luồng sử dụng thời điểm Tuy nhiên, chi phí cho việc lại làm giảm hiệu suất thời gian ứng dụng xuống 3, lần • Phương thức wait() làm luồng vào trạng th ngủ • Phương thức notify() đánh thức luồng thứ danh sách luồng chờ đối tượng monitor • Phương thức notifyAll() đánh thức tất luồng danh sách luồng chờ đối tượng monitor • Deadlock xẩy luồng có phụ thuộc vòng cặp đối tượng quản lý việc đồng (synchronized object) ... int n= Thread.activeCount(); // Đếm số luồng tích cực JVM System.out.println("Number of active threads: " + n); String t1Name = t1.getName(); // lấy tên luồng String t2Name = t2.getName(); System.out.println("Name... qủa luồng tích cực : luồng gom rác, luồng mẹ luồng t1,t2 Kết This is main thread Number of active threads: 4 Name of t1 thread:Thread-1 Name of t2 thread:Thread-2 Is t1 thread a daemon? :false Is... luồng OutNum Obj2 = new OutNum(monitor,num++); OutNum Obj3 = new OutNum(monitor,num++); // wait for threads to end try Output 10 - done { Obj1.t.join(); Output 11 - done Obj2.t.join(); Output 12 -

Ngày đăng: 04/11/2019, 23:54

TÀI LIỆU CÙNG NGƯỜI DÙNG

  • Đang cập nhật ...

TÀI LIỆU LIÊN QUAN

w