Bài giảng Công nghệ Java - Chương 7: Threads. Tiến trình - Trần Quang Diệu

Nội dung

1- Luồng và đa luồng

2- Luồng trong Java

3- Trạng thái của luồng

4- Lập trình luồng trong Java

5- Độ ưu tiên của luồng

6- Đồng bộ giữa các luồng

7- Deadlock

8- Cơ chế Chờ-nhận biết

9- Tóm tắt

Luồng và đa luồng

• Luồng- thread: Một dòng các lệnh mà CPU phải thực thi.

• Các hệ điều hành mới cho phép nhiều luồng được thực thi

đồng thời. Chúng ta đã quen với việc mở nhiều ứng dụng

trong 1 lần làm việc với máy tính  Nhiều ứng dụng được

nạp.

• Như vậy

– Một luồng là một chuỗi các lệnh nằm trong bộ nhớ ( chương trình đã

được nạp).

– 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ò chơi là 10 luồng.

pdf 44 trang kimcuc 2820
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng Công nghệ Java - Chương 7: Threads. Tiến trình - Trần Quang Diệu", để tải tài liệu gốc về máy hãy click vào nút Download ở trên

Tóm tắt nội dung tài liệu: Bài giảng Công nghệ Java - Chương 7: Threads. Tiến trình - Trần Quang Diệu

Bài giảng Công nghệ Java - Chương 7: Threads. Tiến trình - Trần Quang Diệu
CÔNG NGHỆ JAVA
CH7. THREADS – TIẾN TRÌNH
Quang Dieu Tran PhD
 1
Nội dung
1- Luồng và đa luồng
2- Luồng trong Java
3- Trạng thái của luồng
4- Lập trình luồng trong Java
5- Độ ưu tiên của luồng
6- Đồng bộ giữa các luồng
7- Deadlock
8- Cơ chế Chờ-nhận biết
9- Tóm tắt
 2
Luồng và đa luồng
• Luồng- thread: Một dòng các lệnh mà CPU phải thực thi.
• Các hệ điều hành mới cho phép nhiều luồng được thực thi
đồng thời. Chúng ta đã quen với việc mở nhiều ứng dụng
trong 1 lần làm việc với máy tính Nhiều ứng dụng được
nạp.
• Như vậy
– Một luồng là một chuỗi các lệnh nằm trong bộ nhớ ( chương trình đã
được nạp).
– 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ò chơi là 10 luồng.
 3
Kỹ thuật đa luồng
• Với máy có m CPU chạy m luồng Mỗi CPU chạy 1 luồng 
Hiệu quả.
• 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 1 CPU chạy đồng thời k luồng với k>1. Các luồng được 
quản lý bằng 1 hàng đợi, mỗi luồng được cấp phát 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ồng Hiệu suất mỗi 
chương trình sẽ kém. 
 4
Lợi ích của đa luồng
• Tăng hiệu suất sử dụng CPU: Phần lớn thời gian thực thi của 
1 ứng dụng là chờ đợi nhập liệu từ user hiệu suất sử dụng 
CPU chưa hiệu qủa.
• Tạo được sự đồng bộ giữa các đối tượng: Thí dụ như 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 (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 (eye-
catching) và quyến rũ (captivating).
• Quản lý được thời gian trong các ứng dụng như thi online, 
thời gian chơi một trò chơi.
 5
Luồng trong Java
 Main thread - luồng chính : là luồng chứa các luồng 
khác. Đây chính là luồng cho Java. Application hiện 
hành (mức toàn application).
 Child thread - luồng con : là luồng được tạo ra từ 
luồng khác.
 Khi 1 application thực thi, main thread được chạy, 
khi gặp các phát biểu phát sinh luồng con, các luồng 
con được khởi tạo. Vào thời điểm luồng chính kết 
thúc, application kết thúc.
 Java cung cấp lớp Thread mô tả 1 luồng trong gói 
java.lang
 6
Trạng thái của luồng
Sinh ra (Born)
new Thread()
Sẵn sàng 
( Ready )
Đang chạy
( Running )
Ngủ 1 lúc
( Sleeping 
)
Bị tạm hoãn
( Suspended 
)
Bị khóa 
( Blocked )
Đã chết 
( Dead )
Đang chờ
( Waiting )
khi chờ các biến 
cố như xuất/nhập
start()
notify()
wait() sleep() wait()
stop() hay chạy xong
Hành vi để buộc 
luồng chuyển 
trạng thái
run()
Hết thời gian ngủ
notify()
 7
Trạng thái của luồng
• 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 ở mục sau. Phương thức wait()
giúp đưa 1 luồng vào trạng thái chờ.
 8
Trạ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.
• Khi 1 suspended thread được mang ra thực thi tiếp, 
trạng thái của luồng là resumed. Phương thức 
resume() – version cũ/ notify() trong Java 2 được 
dùng cho mục đí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 (dead).
 9
Lập trình luồng trong Java
• Cách 1: Xây dựng 1 lớp con của lớp java.lang.Thread, 
override hành vi run() để phù hợp với mục đích bài 
toán.
• Cách 2: Xây dựng 1 lớp có hiện thực interface 
Runnable
– 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
 10
Tham khảo lớp Thread
 11
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
}
}
 12
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
}
}
 13
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()
 14
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, long 
stacksize)
• Thread (ThreadGroup group, String Name)
• target : luồng cha
• name: tên gọi của luồng được tạo ra
 15
Hai loại luồng
• Luồng Daemon: luồng hệ thống, chạy ở mức 
nền (background- chạy ngầm), là những luồng 
cung cấp các dịch vụ cho các luồng khác. Các 
quá trình trong JVM chỉ tồn tại khi các luồng 
daemon tồn tại. JVM có ít nhất 1 luồng 
daemon là luồng “garbage collection”
• Luồng do user tạo ra.
 16
Methods thông dụng của lớp Thread
Method Mục đích
static int enumerate (Thread
[] t)
Sao chép các luồng đang tích cực vào 1
mảng từ các nhóm luồng và nhóm con
của chúng.
final String getName() Lấy tên của luồng
final boolean isAlive() Kiểm tra luồng còn sống hay không?
final void setName( String
NewName)
Đặt tên mới cho luồng
final void join () throws
interruptedException
Chờ luồng này chết
public final boolean
isDaemon()
Kiểm tra xem luồng này có phải là
luồng daemon
void setDaemon(boolean on) on=true : luồng là daemon
on=false : luồng của user
 17
Methods thông dụng của lớp Thread
Method Mục đích
static void sleep (long
milisec)
Trì hoãn luồng 1 thời gian
void start() thực thi luồng
static int activeCount() Đếm số luồng đang tích cực
static void yield() Tạm dừng luồng hiện hành để các
luồng khác tiếp tục thực thi
 18
Minh 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(); 
t.Create(); // tạo luồng con
}
}
Kết qủa:
This is main thread
This is child thread
Pres any key to continue
 19
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();
}
}
Kết qủa:
This is main thread
This is child thread
Pres any key to continue
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()
 20
Minh họa một số methods của 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 đ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.
 21
Minh họa về trạng thai của 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 5 secs.");
}
catch( InterruptedException e)
{ System.out.println("thread is interrupted!");
}
}
public static void main (String args[])
{ new Thread4();
}
}
t thread is born and ready.
t thread is running.
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
 22
Độ ư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 thi Có nhu cầu thay đổi độ 
ưu tiên của luồng. Java cung cấp 3 hằng mô tả độ ưu tiên của 
1 luồng (các độ ưu tiên khác dùng 1 số nguyên từ 1.. 10).
• NORM_PRIORITY : mang trị 5
• MAX_PRIORITY : mang trị 10
• MIN_PRIORITY : mang trị 1
• Độ ưu tiên mặc định của 1 luồng là NORMAL_PRIORITY. Luồng 
con có cùng độ ưu tiên với luồng cha (do đặc điểm thừa kế). 
 23
Thao tác với độ ưu tiên của luồng
• final void setPriority( int newPriority)
• final int getPriority()
Như vậy, các điều kiện để 1 luồng không được thực 
thi:
• Luồng không có được độ ưu tiên cao nhất để dành 
lấy thời gian của CPU.
• Luồng bị cưỡng bức ngủ bằng hành vi sleep().
• Luồng bị chờ do hành vi wait().
• Luồng bị tường minh nhận hành vi yield().
• Luồng bị khóa vì đang chờ I/O
 24
Minh họa về độ ưu tiên của 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:" + 
Child.getName());
System.out.println("Priority of child:" + 
Child.getPriority()); 
}
public static void main (String args[])
{ Thread5 t = new Thread5();
t.start();
t.setName("Parent thread");
}
}
Name of current thread:Parent thread
Piority of current thread:5
Name of child:Child thread
Priority of child:5
Press any key to continue...
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
 25
Đồ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 được có thể 
không nhất quán.
 Nếu để cho t2 ghi m trước rồi t1 đọc sau thì t1 đọc 
được dữ liệu nhất quán tại thời điểm đó.
 Cần có cơ chế để chỉ cho phép 1 luồng được truy 
xuất dữ liệu chung (shared data) tại 1 thời điểm.
• Kỹ thuật này gọi là “ĐỒNG BỘ HÓA –
SYNCHRONIZATION”
 26
Kỹ thuật cơ bản về đồng bộ hóa
• Tạo ra 1 đối tượng quản lý sự đồng bộ của 1 thao tác dữ 
liệu của các luồng bằng cách thực thi hộ một tác vụ của các 
luồng mỗi lần chỉ cho 1 luồng bằng từ khóa synchronized
• Mọ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ì phải làm 1 tác vụ thì 
nhờ đối tượng monitor làm hộ hoặc là 1 biến boolean để 
nhận biết đã có 1 luồng đang thực thi.
• Luồng đang được chiếu cố gọi là luồng đang có monitor
 27
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.");
try
{ Thread.sleep(500); // current thread sleep 1/2 sec
}
catch (InterruptedException e)
{ System.out.println ("Thread is interrupted!");
}
}
}
Chương trình sau sẽ xuất 3 số 10,11, 12 ra màn hình, mỗi số được 1
luồng thực thi.
Từ khóa synchronized khai báo có quản lý việc đồng bộ các luồng 28
Minh 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 )
{ monitor= moni;
number = n;
t = new Thread(this);
t.start();
}
// khi luồng chạy, số number được xuất bởi monitor
public void run() { monitor.Display(number); }
}
 29
Minh họa về đồng bộ các luồng bằng MONITOR
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
try
{ Obj1.t.join();
Obj2.t.join();
Obj3.t.join();
}
catch(InterruptedException e)
{ System.out.println ("Thread was interrupted!"); }
}
}
3 luồng có 3 trị 
khác nhau là 
10,11, 12 nhưng 
có chung 1 
monitor
Ba luồng cùng 
đơ
Output 10 - done.
Output 11 - done.
Output 12 - done.
Press any key to continue....
 30
Kỹ thuật đồng bộ luồng theo khối
• Đồng bộ một khối tác vụ.
• Người lập trình có thể không muốn dùng các 
synchronized method để đồng bộ truy xuất 
đến đối tượng.
• Các lớp được cung cấp bởi các thư viện hay 
do “một ai đó” cung cấp – lớp đã xây dựng-
nên không thể thêm từ khóa synchonized 
vào được các method này.
 31
Kỹ thuật đồng bộ luồng theo khối
• Cú pháp đồng bộ khối
synchronized (Object)
{ <các lời gọi methods của Object
cần phải được đồng bộ>
}
• Buộc phải có { } dù chỉ có 1 phát biểu
 32
Minh họa đồng bộ khối
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!");
}
}
}
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)
 33
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
try
{ Obj1.t.join();
Obj2.t.join();
Obj3.t.join();
}
catch(InterruptedException e)
{ System.out.println ("Thread was interrupted!"); 
}
}
}
 34
Minh họa đồng bộ khối
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);
}
}
}
 35
Deadlock
• Deadlock – tình huống bế tắc, đóng băng- xẩy ra khi 
các luồng chờ tài nguyên (monitor) của nhau hình 
thành một chu trình. Deadlock hiếm khi xẩy ra.
 36
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 nhau) sử dụng
các final methods của lớp 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.
 37
Cơ chế wait-notify
• Phương thức wait() : Luồng nhả monitor để đi vào 
trạng thái sleep cho đến khi 1 luồng khác vào cùng 
monitor và gọi phương thức notify.
• 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 luồng 
đang ngủ để chúng biết rằng luồng hiện hành đã gọi 
phương thức wait(). Khi tất cả các luồng đang ngủ 
thức dậy, luồng có ưu tiên cao nhất sẽ nắm giữ 
monitor và thực thi.
 38
Chú ý đối với phương thức wait
• Luồng gọi phương thức wait() sẽ nhả CPU, 
thôi không dùng CPU nữa.
• Luồng gọi phương thức wait() sẽ nhả monitor, 
thôi không khóa (lock) monitor nữa.
• Luồng gọi phương thức wait() sẽ được đưa 
vào danh sách hàng đợi monitor (monitor 
waiting pool) 
 39
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.
 40
Chú ý đố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
 41
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 toán cơ chế quản lý các 
luồng. Do vậy trong caù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ập 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ủa ứ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 thúc ứng dụng vì 
luồng main chỉ kết thúc khi tất cả các luồng con của nó đã kết thúc.
 42
Tóm tắt
• Hiện thực 1 luồng bằng 1 trong 2 cách:
• Hiện thực 1 lớp con của lớp Thread, override phương thức run()
của lớp này.
• 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ủa 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().
 43
Tó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 monitor.
• Phương thức notifyAll() sẽ đánh thức tất cả các luồng trong 
danh sách luồng đang chờ trên cùng 1 đối tượng monitor.
• Deadlock xẩy ra khi 2 luồng có sự phụ thuộc vòng trên một 
cặp đối tượng quản lý việc đồng bộ (synchronized object).
 44

File đính kèm:

  • pdfbai_giang_cong_nghe_java_chuong_7_threads_tien_trinh_tran_qu.pdf