Quá trình (process) là trạng thái tức thời của một chương trình đang chạy trên máy tính. Nó bao gồm bộ nhớ cần thiết để chạy chương trình (không gian địa chỉ của quá trình) và khả năng kiểm soát hiện trạng của bộ xử lý trong quá trình thực thi chương trình (tiến trình điều khiển của quá trình).
Trang 3– 1 application thông thường khi thực thi là 1 luồng.
– Trong 1 application có thểcó nhiều luồng Thí dụ
chuyểnñộng của 10 ñối tượng hiện hành trong 1 trò
thời gian mà CPU thực thi là ti (cơchếtime-slicing –
phân chia tài nguyên thời gian) Luồngở ñỉnh hàngñợi
ñược lấy rañểthực thi trước, sau ti thời gian của mình,
luồng nàyñượcñưa vào cuối hàngñợi và CPU lấy ra
luồng kếtiếp
Với máy chỉcó 1 CPU mà lại chạy k luồngHiệu suất
mỗi chương trình sẽkém
Trang 4nhưtrong 1 trò chơi, các nhân vật cùng nhau chuyển
ñộng Trong 1 trang Web, tạoñược sự ñồng thời của
cácñường diềm (marquee) nhưthanh tiêuñề ñộng
Main thread - lu ồ ng chính : là luồ ng ch ứ a các
Child thread - lu ồ ng con : là luồ ng ñượ c t ạ o ra
luồng chính kết thúc, application kết thúc
Trang 59.4- Tr ạ ng thái c ủ a lu ồ ng
Sinh ra (Born) new Thread()
stop() hay ch ạ y xong Hành vi ñể buộc
Một luồng sau khi sinh ra (born) khôngñược chạy ngay
mà chỉlà sẵn sàng (ready) chạy Chỉkhi nào phương
thức start()ñược gọi thì luồng mới thực thi (chạy code
phương thức run())
Luồngñang thực thi có thểbịtạm ngưng bằng phương
thức sleep() một thời khoảng và sẽlại ready sau khiñáo
hạn thời gian Luồngñang ng ủ không sửdụng tài
nguyên CPU
Khi nhiều luồng cùngñược thực thi, nếu có 1 luồng giữ
tài nguyên mà không nhảra sẽlàm cho các luồng khác
không dùngñược tài nguyên này (ñói tài nguyên) Để
tránh tình huống này, Java cung cấp cơchế
Wait-Notify( ñợ i-nh ậ n bi ế t) và cơchếnàyñược trình bàyở
Trang 6Tr ạ ng thái c ủ a lu ồ ng
Khi một 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()
trong Java 2 dùng cho m ục ñích này.
Java 2 ñc dùng cho mc ñích này.
Khi 1 lu ồ ng ch ờ bi ế n c ố nh ư xu ấ t/nh ậ p d ữ li ệ u
Lu ồ ng r ơ i vào tr ạ ng thái blocked.
Khi 1 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
– Không cần import java.lang vì là gói cơbản
– java.lang.Thread là lớp Java xây dựng sẵnñã hiện
thực interface Runnable
– Interface java.lang.Runnable chỉcó 1 method run()
– Tham khảo thêm trong gói java.lange
Trang 7Tham kh ả o l ớ p Thread
9.5.1- T ạ o lu ồ ng là l ớ p con c ủ a l ớ p Thread
class MyThread extends Thread
{ // d ữ li ệ u + hành vi c ủ a l ớ p
public void run()
{ // hi ệ n th ự c code ph ụ thu ộ c bài toán
}
}
Trang 89.5.2- T ạ o lu ồ ng v ớ i interface Runnable
class MyThread implements Runnable
{ // d ữ li ệ u + hành vi c ủ a l ớ p
public void run()
{ // hi ệ n th ự c code ph ụ thu ộ c bài toán
}
}
9.5.3- Kh ở i t ạ o và th ự c thi 1 lu ồ ng
MyThread t = new MyThread(); // t ạ o 1 lu ồ ng
t.start(); // ch ỉ th ị cho lu ồ ng th ự c thi
Hành vi start() s ẽ t ự ñộ ng g ọ i hành vi run()
Trang 99.5.4- Thread Constructors
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,
Trang 109.5.6- Methods thông d ụ ng c ủ a l ớ p Thread
on=true : luồng là daemon on=false : luồng của user
void setDaemon(boolean on)
Kiểm tra xem luồng này có phải làluồng daemon
public final boolean
isDaemon()
Chờ luồng này chết
final void join () throws
interruptedException
Đặt tên mới cho luồng
final void setName( String
NewName)
Kiểm tra luồng còn sống hay không?
final boolean isAlive()
Lấy tên của luồng
final String getName()
Sao chép các luồng ñang hoạt ñộng(active) vào 1 mảng từ các nhóm luồng
và nhóm con của chúng
static int enumerate (Thread
[] t)
Mục ñích Method
9.5.6- Methods thông d ụ ng c ủ a l ớ p Thread
Tạm dừng luồng hiện hành ñể cácluồng khác tiếp tục thực thi
static void yield()
Đếm số luồng ñang hoạt ñộng
static int activeCount()
thực thi luồng
void start()
Trì hoãn luồng 1 thời gian
static void sleep (long
milisec)
Mục ñích Method
Trang 11Minh h ọ a t ạ o lu ồ ng v ớ i l ớ p Thread
// 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 con c ủ a lu ồ ng cha hi ệ n 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();
Minh h ọ a t ạ o lu ồ ng v ớ i l ớ p interface Runnable
class Thread2 implements Runnable
{ public void Create()
{ Thread t = new Thread(this);
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();
}
Khi xây d ự ng lu ồ ng b ằ ng interface Runable, ph ả i khai báo 1 ñố i t ượ ng Thread và g ọ i hành vi start() ñể hành vi này g ọ i
run()
Trang 12MInh họa một sốmethods của Thread
class Thread3 implements Runnable // Thread3.java
public void run()
{ int n= Thread.activeCount(); // Đế m s ố lu ồ ng ñ ang tích c ự c trong JVM
System.out.println("Number of active threads:" + n);
String t1Name = t1.getName(); // l ấ y tên c ủ a 2 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();
}
}
K ế t qu ả
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ên m ặ c ñị nh c ủ a lu ồ ng là Thread-n, v ớ i n là s ố th ứ t ự khi lu ồ ng ñượ c t ạ o ra
K ế t q ủ a là 4 lu ồ ng tích c ự c : lu ồ ng gom rác, lu ồ ng m ẹ và 2
lu ồ ng t1,t2.
Minh họa vềtrạng thaí của luồng
class Thread4 extends Thread// // Thread4.java
t is awaked and running again after 5 secs.
Press any key to continue
Dòng này xu ấ t sau 5 giây
so v ớ i dòng tr ướ c
Trang 139.6- Độ ư u tiên c ủ a lu ồ ng
Các luồng cùng chia sẻthời gian của CPU Luồngở
cuối hàngñợi sẽlâuñược CPU thực thiCó nhu cầu
thayñổiñộ ưu tiên của luồng Java cung cấp 3 hằng mô
final void setPriority( int newPriority)
final int getPriority()
Trang 14Minh h ọ a v ề ñộ ư u tiên c ủ a lu ồ ng
class Thread5 extends Thread// Thread4.java
{
public void run()
{ Thread Child = new Thread(this);
public static void main (String args[])
{ Thread5 t = new Thread5();
N ế u trong main(), thêm dòng t.setPriority (8); tr ướ c dòng t.start();
ta có k ế t q ủ a là 8 thay vì 5
9.7- Đồ ng b ộ các lu ồ ng
Tình hu ố ng: Có hai luồ ng t1, t2 cùng truy xu ấ t 1
ñố i t ượ ng d ữ li ệ u là bi ế n m t1 mu ố n ñọ c bi ế n m
còn t2 muốn ghi biến m d ữ li ệ u mà t1 ñọ c
Trang 15Mọiñối tượng luồngñềuñượcñối tượng quản lý này
quan sát (MONITOR) bằng cách cho mọiñối tượng
luồng có dữliệu làñối tượng monitor này và thay vì
Minh họa về ñồng bộcác luồng bằng MONITOR
// Monitor1.java – L ớ p làm nhi ệ m v ụ xu ấ t h ộ 1 s ố num
class Monitor1
{ synchronized void Display (int num)
{ System.out.println("Output " + num + " - done.");
Trang 16Minh họa về ñồng bộcác luồng bằng MONITOR
class OutNum implements Runnable // lu ồ ng
{ Monitor1 monitor; // Lu ồ ng có d ữ li ệ u là monitor
int number; // dữ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 )
// khi lu ồ ng ch ạ y, s ố number ñượ c xu ấ t b ở i monitor
public void run() { monitor.Display(number); }
}
class Synchro // l ớ p c ủ a ch ươ ng trình chính
{ public static void main (String args[])
{ Monitor1 monitor = new Monitor1();
int num = 10;
OutNum Obj1 = new OutNum(monitor,num++);
OutNum Obj2 = new OutNum(monitor,num++);
OutNum Obj3 = new OutNum(monitor,num++);
// wait for 3 threads to end
có chung 1 monitor
Trang 17hay do “m ộ t ai ñ ó” cung c ấ p – l ớ p ñ ã xây
d ự ng- nên không th ể thêm t ừ khóa
Trang 18Minh h ọ a ñồ ng b ộ kh ố i
class Monitor2 // Monitor2.java
{ void Display (int num)
{ System.out.println("Output " + num + " - done.");
Ch ươ ng trình sau vi ế t l ạ i ch ươ ng trình tr ướ c, b ỏ qua t ừ khóa
synchronized trong l ớ p Monitor1 ( ở ñây gọ i là l ớ p Monitor2)
Minh h ọ a ñồ ng b ộ 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 3 threads to end
Trang 209.8- Deadlock
ngủ300 mili giây.Vì chia sẻthời gian CPU nên t1 ngủ
trước và t2 ngủsau (xem phương thức run())
Khi t1 thức dậy (wake up), phương thức Synchro() của
ñối tượng monitor của d2 (chứa luồng t2) ñược gọi nhưng
luồng t2 ñang ngủnên phương thức này chưa thểthực
thi
Khi t2 thức dậy (wake up), phương thức Synchro() của
ñối tượng monitor của d1 (chứa luồng t1) ñược gọi nhưng
luồng t1 cũngñang ngủnên phương thức này chưa thể
thực thi
Nhưvậy chương trình sẽ ñóng băng (blocked) không làm
gìñược nữa
Trang 219.9- C ơ ch ế ch ờ - nh ậ n bi ế t
Java cung c ấ p s ẵ n m ộ t c ơ ch ế giao ti ế p
liên qúa trình (inter-process mechanism)
ñể các lu ồ ng có th ể g ọ i nhau (yêu c ầ u
Object: wait() , notify() , notifyAll() Nh ư
v ậ y m ọ i l ớ p ñề u có th ể s ử d ụ ng chúng và
các ph ươ ng th ứ c này ch ỉ có th ể ñượ c g ọ i
trong các synchronized methods
C ơ ch ế wait-notify
Ph ươ ng th ứ c wait() : Lu ồ ng nh ả monitor ñể ñ i
Ph ươ ng th ứ c notify() : Lu ồ ng th ứ c d ậ y (wake
up) và nh ậ n bi ế t (notify) r ằ ng lu ồ ng th ứ nh ấ t ñ ã
g ọ i wait().
Ph ươ ng th ứ c notifyAll() : Đ ánh th ứ c t ấ t c ả các
Trang 22Lu ồ ng g ọ i ph ươ ng th ứ c wait() s ẽ ñượ c
ñư a vào danh sách hàng ñợ i monitor
(monitor waiting pool)
Chú ý ñố i v ớ i ph ươ ng th ứ c notify
M ộ t lu ồ ng ñ ang ng ủ ñượ c ñư a ra kh ỏ i
monitor waiting pool và ñ i vào tr ạ ng thái
ready.
Lu ồ ng v ừ a th ứ c gi ấ c (notify) ph ả i giành l ạ i
monitor và khóa monitor l ạ i không cho
lu ồ ng khác chi ế m ñể lu ồ ng này ñượ c th ự c
thi.
Trang 23Chú ý ñố i v ớ i ph ươ ng th ứ c notifyAll
Lu ồ ng ñ ang th ự c thi c ả nh báo cho t ấ t c ả
các lu ồ ng ñ ang ng ủ r ằ ng “Tôi ñ i ng ủ ñ ây,
các b ạ n d ậ y ñể làm vi ệ c”.
Lu ồ ng ở ñầ u danh sách monitor waiting
pool ñượ c vào tr ạ ng thái ready
Bài toán 5 tri ế t gia ă n t ố i v ớ i 5
chi ế c ñũ a
Trang 249.10- Tĩm t ắ t
Luồng là biện pháp chia cơng việc thành cácđơn vịcụthể
(concrete) nên cĩ thể được dùngđểthay thếvịng lặp
L p trìnhđa luồng làm tăng hiệu suất CPU trên những hệ
thống “bận rộn” Tuy nhiên hiệu suất của từngứng dụng lại bị
giảmđang kể(chậm ba bốn lần do các tác vụ đồng bộhĩa),
qúa trình biên dịch cũng chậm vì trình biên dịch phải tính tốn
cơchếquản lý các luồng Do vậy trong cácứng dụngđịi hỏi
yếu tốhiệu suất thời gian là quan trọng, nên tránh sửd ng kỹ
thuậtđồng bộhĩa Nhiều lập trình viên khơng thích lậ
trìnhđa luồng mà chỉdùng lập trình lập trìnhđơn luồngđể
tăng hiệu suất củ ứng dụng
Java cung cấp kỹthuật lập trìnhđa luồng bằng lớp Thread và
interface Runnable.
Khi 1 ứng dụng Java thực thi, cĩ 1 luồngđang chạyđĩ là
luồng chính (main thread) Luồng chính rất quan trọng vì (1)
Đây là luồng cĩ thểsinh ra các luồng con, (2) Quản lý việc kết
Khai báo lớp mà ta xây dựng là implement của interface
Runnable vàđịnh nghĩa phương thức run().
Mỗi java thread cĩ 1 độ ưu tiên từ1 (MIN) đến 10 (MAX) với
5 là trịmặcđịnh JVM khơng bao giờthayđổiđộ ưu tiên củ
luồng
Cĩ 8 contructor của lớp Thread nhưng 2 constructor thường
dùng: Thread() và Thread(String TênLu ồ ng),
Thread( Đố iT ượ ngCh ứ a).
Các phương thức Thread.suspend(), Thread.resume(),
Thread.stop() khơng cịnđược dùng nữa kểtừJava 2
Luồng daemon là luồng chạy ngầm nhằm cung cấp dịch vụ
cho các luồng khác Nếu muốn 1 luồng là daemon, hãy dùng
public final void setDeamon (boolean) và kiểm tra 1 luồng
cĩ là daemon hay khơng, hãy dùng public final boolean
isDaemon().
Trang 25Tóm t ắ t
Dữliệu có thểbịmất nhất quán(hưhỏng) khi có 2 luồng
cùng truy xuất dữliệu tại cùng 1 thờiñiểm
Đồng bộlà 1quá trình bảoñảm tài nguyên (dữ liệu,
file,…) chỉ ñược 1 luồng sửdụng tại 1 thờiñiểm Tuy
nhiên, chi phí cho việc này lại làm giảm hiệu suất thời
gian củaứng dụng xu ố ng 3, 4 l ầ n.
Phương thức wait() sẽlàm 1 luồngñi vào trạng thaí
ngủ
Phương thức notify() sẽ ñánh thức luồng thứnhất trong
danh sách luồngñang chờtrên cùng 1 ñối tượng