41
A TUYN
Mc tiêu:
Sau khi kt thúc ching này, bn có th:
nh ngha mt lung
Mô t đa tuyn
To và qun lý lung
Hiu đc vòng đi ca lung
Mô t mt lung him
Gii thích tp hp các lung u tiên nh th nào
Gii thích đc s cn thit ca s đng b
Hiu đc cách thêm vào các t khoá synchronized (đng b) nh th
nào
Lit kê nhng điu không thun li ca s đng b
Gii thích vai trò ca các phng thc wait() (đi), notify() (thông
báo) và notifyAll().
Mô t mt điu kin b tc (deadlock).
1. Gii thiu
Mt lung là mt thuc tính duy nht ca Java. Nó là đn v nh nht ca đon
mã có th thi hành đc mà thc hin mt công vic riêng bit. Ngôn ng Java và máy o
Java c hai là các h thng đc phân lung
2. a tuyn
Java h tr đa tuyn, mà có kh nng làm vic vi nhiu lung. Mt ng dng có
th bao hàm nhiu lung. Mi lung đc đng ký mt công vic riêng bit, mà chúng
đc thc thi đng thi vi các lung khác.
a tuyn gi thi gian nhàn ri ca h thng thành nh nht. iu này cho phép
bn vit các chng trình có hiu qu cao vi s tn dng CPU là ti đa. Mi phn ca
chng trình đc gi mt lung, mi lung đnh ngha mt đng dn khác nhau ca s
thc hin. ây là mt thit k chuyên dùng ca s đa nhim.
Trong s đa nhim, nhiu chng chng trình chy đng thi, mi chng trình
có ít nht mt lung trong nó. Mt vi x lý thc thi tt c các chng trình. Cho dù nó có
th xut hin mà các chng trình đã đc thc thi đng thi, trên thc t b vi x lý
nhy qua li gia các tin trình.
3. To và qun lý lung
Khi các chng trình Java đc thc thi, lung chính luôn luôn đang đc thc
hin. ây là 2 nguyên nhân quan trng đi vi lung chính:
Các lung con s đc to ra t nó.
Nó là lung cui cùng kt thúc vic thc hin. Trong chc lát lung
chính ngng thc thi, chng trình b chm dt.
Cho dù lung chính đc to ra mt cách t đng vi chng trình thc thi, nó có
th đc điu khin thông qua mt lung đi tng.
Các lung có th đc to ra t hai con đng:
Trình bày lp nh là mt lp con ca lp lung, ni mà phng thc run() ca
lp lung cn đc ghi đè. Ly ví d:
42
Class Mydemo extends Thread
{
//Class definition
public void run()
{
//thc thi
}
}
Trình bày mt lp mà lp này thc hin lp Runnable. Ri thì đnh ngha
phng thc run().
Class Mydemo implements Runnable
{
//Class definition
public void run()
{
//thc thi
}
}
Chng trình 8.1 s ch ra s điu khin lung chính nh th nào
Chng trình 8.1
import java.io.*;
public class Mythread extends Thread{
/**
* Mythread constructor comment.
*/
public static void main(String args[]){
Thread t = Thread.currentThread();
System.out.println("The current Thread is :" + t);
t.setName("MyJavaThread");
System.out.println("The thread is now named: " + t);
try{
for(int i = 0; i <3;i++){
System.out.println(i);
Thread.sleep(1500);
}
}catch(InterruptedException e){
System.out.println("Main thread interupted");
}
}
}
Hình sau đây s ch ra kt qu xut ra màn hình ca chng trình trên
43
Hình 8.1 Lung
Trong kt qu xut ra trên
Mi lung trong chng trình Java đc đng ký cho mt quyn u tiên. Máy o
Java không bao gi thay đi quyn u tiên ca lung. Quyn u tiên vn còn là hng s
cho đn khi lung b ngt.
Mi lung có mt giá tr u tiên nm trong khong ca mt
Thread.MIN_PRIORITY ca 1, và mt Thread.MAX_PRIORITY ca 10. Mi lung ph
thuc vào mt nhóm lung, và mi nhóm lung có quyn u tiên ca chính nó. Mi
lung đc nhn mt hng s u tiên ca phng thc Thread.PRIORITY là 5. Mi
lung mi tha k quyn u tiên ca lung mà to ra nó.
Lp lung có vài phng thc khi dng, hai trong s các phng thc khi
dng đc đ cp đn di đây:
public Thread(String threadname)
Cu trúc mt lung vi tên là “threadname”
public Thread()
Cu trúc mt lung vi tên “Thread, đc ràng buc vi mt s; ly ví d,
Thread-1, Thread-2, v.v…
Chng trình bt đu thc thi lung vi vic gi phng thc start(), mà phng
thc này ph thuc vào lp lung. Phng thc này, ln lt, vin dn phng thc
run(), ni mà phng thc đnh ngha tác v đc thc thi. Phng thc này có th vit
đè lên lp con ca lp lung, hoc vi mt đi tng Runnable.
4. Vòng đi ca Lung
[main, 5 , main]
Nhóm lung mà nó ph thuc vào
Quyn u tiên đc đt bi JVM
Tên ca lung
44
Hình 8.3 Vòng đi ca lung
5. Phm vi ca lung và các phng thc ca lp lung
Mt lung đã đc to mi gn đây là trong phm vi “sinh”. Lung không bt
đu chy ngay lp tc sau khi nó đc to ra. Nó đi phng thc start() ca chính nó
đc gi. Cho đn khi, nó là trong phm vi “sn sàng đ chy”. Lung đi vào phm vi
“đang chay” khi h thng đnh rõ v trí lung trong b vi x lý.
Bn có th s dng phng thc sleep() đ tm thi treo s thc thi ca lung.
Lung tr thành sn sàng sau khi phng thc sleep kt thúc thi gian. Lung Sleeping
không s dng b vi x lý. lung đi vào phm vi “waiting” (đi) khi mt lung đang
chy gi phng thc wait() (đi).
Khi các lung khác liên kt vi các đi tng, gi phng thc notify(), lung đi
vào tr li phm vi “ready” (sn sàng) Lung đi vào phm vi “blocked” (khi) khi nó
đang thc thi các phép toán vào/ra (Input/output). Nó đi vào phm vi “ready” (sn sàng)
khi các phng thc vào/ra nó đang đi cho đn khi đc hoàn thành. Lung đi vào
phm vi “dead” (cht) sau khi phng thc run() đã đc thc thi hoàn toàn, hoc khi
phng thc stop() (dng) ca nó đc gi.
Thêm vào các phng thc đã đc đ cp trên, Lp lung cng có các phng
thc sau:
Phng thc Mc đích
Enumerate(Thread t) Sao chép tt c các lung hin hành vào mng đc ch
đnh t nhóm ca các lung, và các nhóm con ca nó.
getName() Tr v tên ca lung
isAlive() Tr v úng, nu lung là vn còn tn ti (sng)
getPriority() Tr v quyn u tiên ca lung
setName(String name) t tên ca lung là tên mà lung đc truyn nh là
mt tham s.
join() i cho đn khi lung cht.
isDaemon(Boolean on) Kim tra nu lung là lung mt lung him.
resume() ánh du lung nh là lung him hoc lung ngi s
dng ph thuc vào giá tr đc truyn vào.
sleep() Hoãn lung mt khoáng thi gian chính xác.
start() Gi phng thc run() đ bt đu mt lung.
45
Bng 8.1 Các phng thc ca mt lp lung
Bng k hoch Round-robin (bng kin ngh ký tên vòng tròn) liên quan đn các
lung vi cùng quyn u tiên đc chim hu quyn u tiên ca mi lung khác. Chúng
chia nh thi gian mt cách t đng trong theo kiu k hoch xoay vòng này.
Phiên bn mi nht ca Java không h tr các phng thc Thread.suspend() (trì
hoãn), Thread.resume() (phc hi) và Thread.stop() (dng), nh là các phng thc
resume() (phc hi) và suspend() (trì hoãn) đc thiên v s đình tr (deadlock), trong
khi phng thc stop() không an toàn.
6. Thi gian biu lung
Hu ht các chng trình Java làm vic vi nhiu lung. CPU cha đng cho vic
chy chng trình ch mt lung ti mt khong thi gian. Hai lung có cùng quyn u
tiên trong mt chng trình hoàn thành trong mt thi gian CPU. Lp trình viên, hoc
máy o Java, hoc h điu hành chc chn rng CPU đc chia s gia các lung. iu
này đc bit nh là bng thi gian biu lung.
Không có máy o Java nào thc thi rành mch cho bng thi gian biu lung. Mt
s nn Java h tr vic chia nh thi gian. đây, mi lung nhn mt phn nh ca thi
gian b vi x lý, đc gi là đnh lng. Lung có th thc thi tác v ca chính nó trong
sut khong thi gian đnh lng đy. Sau khong thi gian này đc vt qua, lung
không đc nhn nhiu thi gian đ tip tc thc hin, ngay c nu nó không đc hoàn
thành vic thc hin ca nó. Lung k tip ca lung có quyn u tiên bng nhau này s
ly khong thi gian thay đi ca b vi x lý. Java là ngi lp thi gian biu chia nh tt
c các lung có cùng quyn u tiên cao.
Phng thc setPriority() ly mt s nguyên (integer) nh là mt tham s có th
hiu chnh quyn u tiên ca mt lung. ây là giá tr có phm vi thay đi t 1 đn 10,
mc khác, phng thc đa ra mt ngoi l (by li) đc gi là
IllegalArgumentException (Chp nhn tham s trái lut)
Phng thc yield() (li nhun) đa ra các lung khác mt kh nng đ thc thi.
Phng thc này đc thích hp cho các h thng không chia nh thi gian (non-time-
sliced), ni mà các lung hin thi hoàn thành vic thc hin trc khi các lung có
quyn u tiên ngang nhau k tip tip qun. đây, bn s gi phng thc yield() ti
nhng khon thi gian riêng bit đ có th tt c các lung có quyn u tiên ngang nhau
chia s thi gian thc thi CPU.
Chng trình 8.2 chng minh quyn u tiên ca lung:
Chng trình 8.2
class PriorityDemo {
Priority t1,t2,t3;
public PriorityDemo(){
t1 = new Priority();
t1.start();
t2 = new Priority();
t2.start();
t3 = new Priority();
t3.start();
}
public static void main(String args[]){
46
new PriorityDemo();
}
class Priority extends Thread implements Runnable{
int sleep;
int prio = 3;
public Priority(){
sleep += 100;
prio++;
setPriority(prio);
}
public void run(){
try{
Thread.sleep(sleep);
System.out.println("Name "+ getName()+" Priority
= "+ getPriority());
}catch(InterruptedException e){
System.out.println(e.getMessage());
}
}
}
}
Kt qu hin th nh hình 8.4
Hình 8.4 Quyn u tiên lung
7. Lung him
Mt chng trình Java b ngt ch sau khi tt c các lung b cht. Có hai kiu
lung trong mt chng trình Java:
Các lung ngi s dng
Lung him
Ngi s dng to ra các lung ngi s dng, trong khi các lung đc ch đnh
nh là lung “background” (nn). Lung him cung cp các dch v cho các lung khác.
Máy o Java thc hin tin trình thoát, khi và ch khi lung him vn còn sng. Máy o
47
Java có ít nht mt lung him đc bit đn nh là lung “garbage collection” (thu
lm nhng d liu vô ngha - dn rác). Lung dn rác thc thi ch khi h thng không
có tác v nào. Nó là mt lung có quyn u tiên thp. Lp lung có hai phng thc đ
tha thun vi các lung him:
public void setDaemon(boolean on)
public boolean isDaemon()
8. a tuyn vi Applets
Trong khi đa tuyn là rt hu dng trong các chng trình ng dng đc lp, nó
cng đáng đc quan tâm vi các ng dng trên Web. a tuyn đc s dng trên web,
cho ví d, trong các trò chi đa phng tin, các bc nh đy sinh khí, hin th các dòng
ch chy qua li trên biu ng, hin th đng h thi gian nh là mt phn ca trang Web
v.vv… Các chc nng này cu thành các trang web làm quyn r và bt mt.
Chng trình Java da trên Applet thng s dng nhiu hn mt lung. Trong
đa tuyn vi Applet, lp java.applet.Applet là lp con đc to ra bi ngi s dng đnh
ngha applet. T đó, Java không h tr nhiu k tha vi các lp, nó không th thc hin
đc trc tip lp con ca lp lung trong các applet. Tuy nhiên, chúng ta s dng mt
đi tng ca lung ngi s dng đã đnh ngha, mà các lung này, ln lt, dn xut t
lp lung. Mt lung đn gin xut hin s đc thc thi ti giao din (Interface)
Runnable
Chng trình 8.3 ch ra điu này thc thi nh th nào:
Chng trình 8.3
import java.awt.*;
import java.applet.*;
public class Myapplet extends Applet implements Runnable {
int i;
Thread t;
/**
* Myapplet constructor comment.
*/
public void init(){
t = new Thread(this);
t.start();
}
public void paint(Graphics g){
g.drawString(" i = "+i,30,30);
}
public void run(){
for(i = 1;i<=20;i++){
try{
repaint();
Thread.sleep(500);
}catch(InterruptedException e){
System.out.println(e.getMessage());
}
48
}
}
}
Trong chng trình này, chúng ta to ra mt Applet đc gi là Myapplet, và
thc thi giao din Runnable đ cung cp kh nng đa tuyn cho applet. Sau đó, chúng ta
to ra mt th nghim (instance) cho lp lung, vi th nghim applet hin thi nh là
mt tham s đ thit lp (khi dng). Ri thì chúng ta vin dn phng thc start() ca
lung th nghim này. Ln lt, ri s vin dn phng thc run(), mà phng thc này
thc s là đim bt đu cho phng thc này. Chúng ta in s t 1 đn 20 vi thi gian
kéo tr là 500 miligiây gia mi s. Phng thc sleep() đc gi đ hoàn thành thi
gian kéo tr này. ây là mt phng thc tnh đc đnh ngha trong lp lung. Nó cho
phép lung nm yên (ng) trong khon thi gian hn ch.
Xut ra ngoài có dng nh sau:
Hình 8.5 a tuyn vi Applet
9. Nhóm lung
Mt lp nhóm lung (ThreadGroup) nm bt mt nhóm ca các lung. Ly ví d,
mt nhóm lung trong mt trình duyt có th qun lý tt c các lung ph thuc vào mt
đn th applet. Tt c các lung trong máy o Java ph thuc vào các nhóm lung mc
đnh. Mi nhóm lung có mt nhóm ngun cha. Vì th, các nhóm t mt cu trúc dng
cây. Nhóm lung “h thng” là gc ca tt c các nhóm lung. Mt nhóm lung có th là
thành phn ca c các lung, và các nhóm lung.
Hai kiu nhóm lung thit lp (khi dng) là:
public ThreadGroup(String str)
đây, “str” là tên ca nhóm lung mi nht đc to ra.
public ThreadGroup(ThreadGroup tgroup, String str)
đây, “tgroup” ch ra lung đang chy hin thi nh là lung cha, “str” là tên ca
nhóm lung đang đc to ra.
Mt s các phng thc trong nhóm lung (ThreadGroup) đc cho nh sau:
public synchronized int activeCount()
49
Tr v s lng các lung kích hot hin hành trong nhóm lung
public sunchronized int activeGroupCount()
Tr v s lng các nhóm hot đng trong nhóm lung
public final String getName()
Tr v tên ca nhóm lung
public final ThreadGroup getParent()
Tr v cha ca nhóm lung
10. S đng b lung
Trong khi đang làm vic vi nhiu lung, nhiu hn mt lung có th mun thâm
nhp cùng bin ti cùng thi đim. Ly ví d, mt lung có th c gng đc d liu, trong
khi lung khác c gng thay đi d liu. Trong trng hp này, d liu có th b sai lc.
Trong nhng trng hp này, bn cn cho phép mt lung hoàn thành trn vn
tác v ca nó (thay đi giá tr), và ri thì cho phép các lung k tip thc thi. Khi hai
hoc nhiu hn các lung cn thâm nhp đn mt tài nguyên đc chia s, bn cn chc
chn rng tài nguyên đó s đc s dng ch bi mt lung ti mt thi đim. Tin trình
này đc gi là “s đng b” (synchronization) đc s dng đ lu tr cho vn đ này,
Java cung cp duy nht, ngôn ng cp cao h tr cho s đng b này. Phng thc “đng
b” (synchronized) báo cho h thng đt mt khóa vòng mt tài nguyên riêng bit.
Mu cht ca s đng b hóa là khái nim “monitor” (s quan sát, giám sát),
cng đc bit nh là mt bng mã “semaphore” (bng mã). Mt “monitor” là mt đi
tng mà đc s dng nh là mt khóa qua li duy nht, hoc “mutex”. Ch mt lung
có th có riêng nó mt s quan sát (monitor) ti mi thi đim đc đa ra. Tt c các
lung khác c gng thâm nhp vào monitor b khóa s b trì hoãn, cho đn khi lung đu
tiên thoát khi monitor. Các lung khác đc báo ch đi monitor. Mt lung mà
monitor ca riêng nó có th thâm nhp tr li cùng monitor.
1. Mã đng b
Tt c các đi tng trong Java đc liên kt vi các monitor (s giám sát) ca
riêng nó. đng nhp vào monitor ca mt đi tng, lp trình viên s dng t khóa
synchronized (đng b) đ gi mt phng thc hiu chnh (modified). Khi mt lung
đang đc thc thi trong phm vi mt phng thc đng b (synchronized), bt k lung
khác hoc phng thc đng b khác mà c gng gi nó trong cùng th nghim s phi
đi.
Chng trình 8.4 chng minh s làm vic ca t khóa synchronized (s đng b).
đây, lp “Target” (mc tiêu) có mt phng thc “display()” (hin th) mà phng
thc này ly mt tham s kiu s nguyên (int). S này đc hin th trong phm vi các
cp ký t “< > # s # <>”. Phng thc “Thread.sleep(1000) tm dng lung hin ti sau
khi phng thc “display()” đc gi.
Thit lp (khi dng) ca lip “Source” ly mt tham chiu đn mt đi tng “t”
ca lp “Target”, và mt bin s nguyên (integer). đây, mt lung mi cng đc to
ra. Lung này gi phng thc run() ca đi tng “t”. Lp chính “Synch” th nghim
lp “Target” nh là “target (mc tiêu), và to ra 3 đi tng ca lp “Source” (ngun).
Cùng đi tng “target” đc truyn cho mi đi tng “Source”. Phng thc “join()”
(gia nhp) làm lung đc gi đi cho đn khi vic gi lung b ngt.