1. Trang chủ
  2. » Công Nghệ Thông Tin

Lập trình Java căn bản - Chương 9 THREADS

25 4 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 25
Dung lượng 259,09 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

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 4

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

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 5

9.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 6

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.

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 7

Tham 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 8

9.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 9

9.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 10

9.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 11

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();

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 12

MInh 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 13

9.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 14

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);

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 15

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ì

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 16

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 )

// 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 17

hay do “m ộ t ai ñ ó” cung c ấ p – l ớ p ñ ã xây

d ự ng- nên không th ể thêm t ừ khóa

Trang 18

Minh 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 20

9.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 21

9.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 22

Lu ồ 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 23

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

Bài toán 5 tri ế t gia ă n t ố i v ớ i 5

chi ế c ñũ a

Trang 24

9.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 25

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

Ngày đăng: 21/05/2021, 14:58