Đa luồng trong java (multithreading in java)

9
19/07/2012 Đa luông trong java (multithreading in Java) | Cộng đồng Java Việt Nam | Java Việt Nam | Java SE, Java… 1/9 congdongjava.com/forum/threads/Đa-luông-trong-java-multithreading-in-java.802/ Dành cho tuy n d ng nhân s CNTT Liên h : Văn Huy 0977118083 Thành Nhân 0909569156 Đa luông trong java (multithreading in Java) Discussion in 'Bài vi ết h ướng d n JSE' started by tranhuyvc, 8/4/10. Đa luông trong java (multithreading in Java) Multithread trong java 1.1 Khái niêm Thread là một đơn vị (nhóm) chứa các dòng điều khiển trong một tiến trình hay ứng dụng, chúng được hệ điều hành sử dụng để thực thi một công việc. Và với cơ chế multithread ứng dụng của ta có thể thực thi nhiều công việc đồng thời . Môi thread se có một chỉ số xác định quyền ưu tiên, thread nào có quyền ưu tiên cao sẽ được thực thi trước, và thấp thì thực thi sau. Việc thực thi và đánh chỉ số ưu tiên sẽ được thực hiện tự động bởi hệ điều hành để tránh một thread nào đợi quá lâu mà không được vào xử lý. Cũng như các ngôn ngữ lập trình khác, java hỗ trợ ngay (trong ban thân ngôn ngữ) khá đây đu các yêucâu, xử lý của một ứng dụng multithread. 1.2 Tao và quanlý thread Trong chương trình java luôn có một thread chính được thực thi , các thread khác sẽ được tạo ra như các thread con, việc mở đầu và kết thúc một ứng dụng được thực hiện bởi thread chính đó. Hình dưới minh họa vòng đời của một thread: Đê tao và quanlý thread trong java, chúng ta dựa vào lớp Thread và Runnable interface Runnable là một interface dùng để các lớp khác implement để sử dung thread. Trong lớp implement đó bắt buộc phải định nghĩa một phương thức là void run(). Ví du ta có 2 lớp StringThread implement Runnable, và một lớp TestClass đê tao ra thread và runnó. public class StringThread implements Runnable { private String str; private int num; StringThread(String s, int n) { str =newString(s); num =n; } /* (non-Javadoc) * @see java.lang.Runnable#run() V Trí VIP Dành cho gi i thi u 1 khóa h c Liên h : Văn Huy 0977118083 Thành Nhân 0909569156 Dành cho gi i thi u khóa h c Liên h : Văn Huy 0977118083 Thành Nhân 0909569156 Dành cho gi i thi u s n ph mcông ngh Liên h : Văn Huy 0977118083 Thành Nhân 0909569156 Trang ch Di n đàn Bài Vi ết H ướng D n Bài viết hướng dn JSE tranhuyvc Administrator Trang ch Di n đàn Din đàn Tìmtrong di n đàn Tìmtrong di n đàn Có gì m i? Có gì m i? Thành viên Giúp đ Đăng Nh p ho c Đăng Ký Tìm kiếm...

Upload: chung-bao-nguyen

Post on 18-Apr-2015

202 views

Category:

Documents


4 download

DESCRIPTION

đa luồng trong java

TRANSCRIPT

Page 1: Đa luồng trong java (multithreading in Java)

19/07/2012 Đa luông trong java (multithreading in Java) | Cộng đồng Java Việt Nam | Java Việt Nam | Java SE, Java…

1/9congdongjava.com/forum/threads/Đa-luông-trong-java-multithreading-in-java.802/

Dành cho tuyển dụng nhân sự CNTT Liên hệ:

Văn Huy 0977118083 Thành Nhân 0909569156

Đa luô�ng trong java (multithreading in Java)Discussion in 'Bài viết hướng dẫn JSE' started by tranhuyvc, 8/4/10.

Đa luông trong java (multithreading in Java)

Multithread trong java

1.1 Khái niê�m

Thread là một đơn vị (nhóm) chứa các dòng điều khiển trong

một tiến trình hay ứng dụng, chúng được hệ điều hành sử dụng

để thực thi một công việc. Và với cơ chế multithread ứng dụng

của ta có thể thực thi nhiều công việc đồng thời. Mô�i thread se�

có một chỉ số xác định quyền ưu tiên, thread nào có quyền ưu

tiên cao sẽ được thực thi trước, và thấp thì thực thi sau. Việc thực thi và

đánh chỉ số ưu tiên sẽ được thực hiện tự động bởi hệ điều hành

để tránh một thread nào đợi quá lâu mà không được vào xử lý.

Cũng như các ngôn ngữ lập trình khác, java hỗ trợ ngay (trong ba�n

thân ngôn ngữ) khá đây đu� các yêu câu, xử lý của một ứng dụng

multithread.

1.2 Ta�o và qua�n lý thread

Trong chương trình java luôn có một thread chính được thực thi, các

thread khác sẽ được tạo ra như các thread con, việc mở đầu và kết

thúc một ứng dụng được thực hiện bởi thread chính đó.

Hình dưới minh họa vòng đời của một thread:

Đê� ta�o và qua�n lý thread trong java, chúng ta dựa vào lớp Thread và

Runnable interface

Runnable là một interface dùng để các lớp khác implement để sử

du�ng thread. Trong lớp implement đó bắt buộc phải định nghĩa

một phương thức là void run().

Ví du� ta có 2 lớp StringThread implement Runnable, và một lớp

TestClass đê� ta�o ra thread và run nó.

public class StringThread implements Runnable {

private String str;

private int num;

StringThread(String s, int n)

{

str = new String(s);

num = n;

}

/* (non-Javadoc)

* @see java.lang.Runnable#run()

Vị Trí VIP Dành cho giới thiệu 1 khóa học

Liên hệ: Văn Huy 0977118083 Thành Nhân 0909569156

Dành cho giới thiệu khóa học Liên hệ:

Văn Huy 0977118083 Thành Nhân 0909569156

Dành cho giới thiệu sản phẩm công nghệ Liên hệ:

Văn Huy 0977118083 Thành Nhân 0909569156

Trang chủ Diễn đàn Bài Viết Hướng Dẫn Bài viết hướng dẫn JSE

tranhuyvcAdministrator

Trang chủ Di

Di

n đàn

n đàn

Diễn đàn

Tìm trong di

Tìm trong di

n đàn

n đàn

Tìm trong diễn đàn Có gì m

Có gì m

i?

i?

Có gì mới?

Thành viên Giúp đỡ

Đăng Nhập hoặc Đăng Ký

Tìm kiếm...

Page 2: Đa luồng trong java (multithreading in Java)

19/07/2012 Đa luông trong java (multithreading in Java) | Cộng đồng Java Việt Nam | Java Việt Nam | Java SE, Java…

2/9congdongjava.com/forum/threads/Đa-luông-trong-java-multithreading-in-java.802/

*/

@Override

public void run() {

for (int i = 1; i <= num; i++)

System.out.print(str + " ");

}

}

public class TestClass {

/**

* @param args

*/

public static void main(String[] args) {

StringThread t = new StringThread("Thread", 10);

new Thread(t).start();

}

}

Kêt qua� in ra màn hình se� là: Thread Thread Thread Thread Thread

Thread Thread Thread Thread Thread

Thread là một lớp viết sẵn trong java, nó implement Runnable

interface. Nếu chúng ta muốn sử dụng thread chỉ cần viết một

lớp và kế thừa (extends) từ lớp Thread này.

Mô�t sô hàm thông du�ng cu�a Thread

• start bắt đầu thực thi thread

• sleep đưa trạng thái về trạng thái đợi (không thực thi nữa)

• resume thực thi lại thread từ trạng thái đợi hoặc dead-lock

• join đợi để cho đến khi thread này chết

• isAlive kiê�m tra thread còn đang sông hay đã bi� kill

• getName lây tên cu�a thread

• getPriority trả về độ ưu tiên của thread

• setName đă�t tên cho thread

• setPriority đặt độ ưu tiên cho thread

• …

Ví dụ tương tự việc sử dụng thread với Runnable interface, chúng ta

cũng có thể kế thừa tự lớp có sẵn là Thread như sau:

class StringThread extends Thread {

public void run() {

System.out.println("Inherit successfully from Thread class!");

}

}

public class TestClass {

public static void main(String[] args) {

StringThread t = new StringThread();

new Thread(t).start();

}

}

Kêt qua� in ra se� là: Inherit successfully from Thread class!

1.3 Các lớp Timer, TimerTask và SchedulingTask

Timer là một lớp tiện ích giúp cho việc lập lịch và kiểm soát

việc thực thi một task vụ nào đó. Ví du� ba�n muôn dùng viê�c

câ�p nhâ�t thông trong 5 phút tới, hay thông tin chỉ được tồn tại

10h sau đó sẽ tự động bị xóa đi,… Mô�t sô hàm thông du�ng

trong Timer như:

• schedule lên lịch để thực thi task khi nào bắt đầu, kêt thúc hay

lă�p la�i, …

Page 3: Đa luồng trong java (multithreading in Java)

19/07/2012 Đa luông trong java (multithreading in Java) | Cộng đồng Java Việt Nam | Java Việt Nam | Java SE, Java…

3/9congdongjava.com/forum/threads/Đa-luông-trong-java-multithreading-in-java.802/

• cancel dừng timer và hủy tất cả các task đã lên lịch trong timer

• purge xóa tất cả các task đã dùng trong hàng đợi timer

TimerTask là một lớp trừu tượng implement Runnable interface, nó giúp

cho việc lập lịch thực thi các thread

Ví dụ ta có một lớp MyTimerTask kế thừa từ TimerTask như bên dưới

class MyTimerTask extends TimerTask {

public void run() {

System.out.println("Running the scheduled task by Timer");

System.gc();

}

}

public class TestClass {

public static void main(String[] args) {

Timer timer = new Timer();

MyTimerTask task = new MyTimerTask();

timer.schedule(task, 3000, 2000);//Execute task after 3 senconds and then

repeat in 2 seconds period

}

}

Kêt qua� in ra màn hình sau 5 giây se� là: Running the scheduled task

by Timer

Running the scheduled task by Timer

1.4 Xử lý các vấn đề chúng trong multithread như synchronized, lock,

dead lock, wait, notify …

Đông bô� (Synchronization) là cơ chế giúp cho đồng bộ việc truy

câ�p cùng tài nguyên cu�a nhiêu thread khác nhau. Như chúng ta

biết vì cơ chế thread là cơ chế làm việc đồng thời do đó có khả

năng một tài nguyên sẽ bị truy cập bởi nhiều thread khác nhau.

Ví dụ ta xây dựng 3 lớp Socola, Producer, Consumer. Lớp Socola chứa

thông tin, lớp Producer tạo thông tin và gán vào cho Socola, Lớp

Consumer se� ăn (tiêu thu�) thông tin đó.

public class TestClass {

public class Socola {

private int contents = 0;

public boolean isRemainingContents;

public synchronized int get() {

//print onto screen

System.out.println("\tConsumer get " + this.contents);

return contents;

}

public synchronized void set(int piContents) {

this.contents = piContents;

//print onto screen

System.out.println("Producer set " + this.contents);

}

}

public class Producer extends Thread {

private Socola socola;

Producer(Socola pSocola) {

socola = pSocola;

}

public void run() {

Page 4: Đa luồng trong java (multithreading in Java)

19/07/2012 Đa luông trong java (multithreading in Java) | Cộng đồng Java Việt Nam | Java Việt Nam | Java SE, Java…

4/9congdongjava.com/forum/threads/Đa-luông-trong-java-multithreading-in-java.802/

for(int i = 0; i < 10; i++) {

socola.set(i);

try {

Thread.sleep(100);

} catch (InterruptedException e) {

}

}

}

}

public class Consumer extends Thread {

private Socola socola;

Consumer(Socola pSocola) {

socola = pSocola;

}

public void run() {

for(int i = 0; i < 10; i++) {

socola.get();

try {

Thread.sleep(100);

} catch (InterruptedException e) {

}

}

}

}

public static void main(String[] args) {

TestClass t = new TestClass();

Socola s = t.new Socola();

Producer p = t.new Producer(s);

Consumer c = t.new Consumer(s);

p.start();

c.start();

}

}

Kêt qua� in ra màn hinh se� không giông nhau ta�i các lân cha�y,

ví du� 1 lân cha�y:

Producer set 0

Consumer get 0

Producer set 1

Consumer get 1

Producer set 2

Consumer get 2

Producer set 3

Consumer get 3

Producer set 4

Consumer get 4

Consumer get 4

Producer set 5

Producer set 6

Consumer get 6

Producer set 7

Consumer get 7

Consumer get 7

Page 5: Đa luồng trong java (multithreading in Java)

19/07/2012 Đa luông trong java (multithreading in Java) | Cộng đồng Java Việt Nam | Java Việt Nam | Java SE, Java…

5/9congdongjava.com/forum/threads/Đa-luông-trong-java-multithreading-in-java.802/

Producer set 8

Consumer get 8

Producer set 9

Từ ví dụ trên ta thấy có chung một tài nguyên là Socola mà có 2 đôi

tượng cùng truy cập � có thê� sinh ra mâu thuâ�n khi truy câ�p

đồng thời. Bây giờ ta muốn là chỉ khi Producer tạo ra thông tin thì

Consumer mới ăn thông tin đó, không muôn Consumer ăn nhiêu lân

cùng mô�t thông tin, khi Producer đang ta�o ra thông tin thì Consumer

đứng chờ, khi nào Producer tạo ra thông tin xong thì Consumer mới vào

ăn thông tin. vậy thì ta phải dùng cơ chế đồng bộ trong java với

các từ khóa synchronized, wait(), notify(), notifyAll() và chi�nh la�i 2

hàm get và set trong lớp Socola như sau:

public synchronized int get() {

while(isRemainingContents == false) {

try {

wait();

} catch (InterruptedException e) {

}

}

isRemainingContents = false;

//print onto screen

System.out.println("\tConsumer get " + this.contents);

//Notify Producer to produce new contents

notifyAll();

return contents;

}

public synchronized void set(int piContents) {

while(isRemainingContents == true) {

try {

wait();

} catch (InterruptedException e) {

}

}

this.contents = piContents;

isRemainingContents = true;

//print onto screen

System.out.println("Producer set " + this.contents);

//Notify Consumer to eat this contents

notifyAll();

}

}

Kết quả in ra luôn luôn như sau:

Producer set 0

Consumer get 0

Producer set 1

Consumer get 1

Producer set 2

Consumer get 2

Producer set 3

Consumer get 3

Page 6: Đa luồng trong java (multithreading in Java)

19/07/2012 Đa luông trong java (multithreading in Java) | Cộng đồng Java Việt Nam | Java Việt Nam | Java SE, Java…

6/9congdongjava.com/forum/threads/Đa-luông-trong-java-multithreading-in-java.802/

Producer set 4

Consumer get 4

Producer set 5

Consumer get 5

Producer set 6

Consumer get 6

Producer set 7

Consumer get 7

Producer set 8

Consumer get 8

Producer set 9

Consumer get 9

Có 3 hàm cân đê� ý:

• wait() đưa thread vào trạng thái chờ khi nào được notify() hoă�c

notifyAll() thì sẽ thực hiện tiếp

• notify() đánh thức thread đang đợi, nếu có nhiều thread đang đợi, thì

một trong những thread đó được đánh thức thôi.

• notifyAll() đánh thức tất cả các thread đang đợi

Note: Nhiêu khi chúng ta không cân hoă�c không thê� đông bô�

nguyên hàm (dùng synchronized) mà chi� cân đông bô� mô�t vài

dòng code truy câ�p tài nguyên, ta có thể dùng khối đồng bộ như

sau:

synchronized(object) {

// Các câu lê�nh cân đông bô�

}

Ví du�: Khi bạn sử dụng lớp Socola là của khách hàng bạn đưa

cho, bạn không thể chỉnh sửa định nghĩa hàm get và set trong

Socola được vậy thì bạn có thể dùng khối đồng bộ bên trên

cũng sẽ cho kết quả tương tự.

Deadlock (khóa chêt) trong xử lý đa luồng xảy là khi mà một thread

được đưa vào trạng thái chờ tài nguyên và không bao giờ được đánh thức

lại vì tại nguyên đó không bao giờ được giải phóng. Để rõ hơn ta ví

du� A, B, C là thread trong trạng thái chờ; rA, rB, rC là tài nguyên dùng

chung và chỉ duy nhất một thread sử dụng trong một thời

điê�m, tài nguyên chỉ được giải phóng khi thread làm xong và không

sử dụng nữa.

• A giữ rA, chờ rB

• B giữ rB, chờ rC

• C giữ rC, chờ rA

Từ ví dụ trên ta thấy A, B, C là những thread đang ở trong trạng thái

chờ tài nguyên, tuy nhiên tài nguyên của chúng không bao giờ được

gia�i phóng, và mãi mãi chúng cứ chờ thôi. Đê� ha�n chê deadlock thì

chúng ta phải đưa ra, ca�i tiên viê�c câp phát, thu hôi tài nguyên

cho các thread và hiê�n này có khá nhiêu thuâ�t toán ca�i tiên

viê�c này, tuy nhiên không có cái nào giúp tránh hoàn toàn deadlock.

1.5 Những lớp tiện ích trong lập trình đa luồng (multithread)

Trong java đã xây dựng một vài lớp giúp hỗ trợ lập trình đa luồng,

chúng được đặt trong gói Concurent như: Semaphore, Lock, Condition,

ConcurrentMap, ConcurrentLinkedQueue, …

Semaphore là một lớp tiện ích đã xây dựng trong java (java 5) dùng

để giới hạn số lượng thread truy cập đến tài nguyên. Đâu tiên

thread cần yêu cầu sự chấp nhận truy cập tài nguyên từ

semaphore băng hàm acquire, và thread sẽ về trạng thái đợi (block)

cho đến khi được chấp nhận, khi thread được chấp nhận nó thực

hiê�n công viê�c cu�a nó xong se� go�i hàm release đê� tra� vê

cho semaphore một sự chấp nhận còn trống để semaphore cấp

cho thread khác.

Lock là một interface được xây dựng nhằm mở rộng hơn việc

quản lý truy cập tài nguyên trong nhiều thread hơn so với cách dùng

synchronized chẳng hạn như có thể hỗ trợ nhiều điều kiện

(condition object) trong lock, hoặc hỗ trợ nhiều thuật toán cho

Page 7: Đa luồng trong java (multithreading in Java)

19/07/2012 Đa luông trong java (multithreading in Java) | Cộng đồng Java Việt Nam | Java Việt Nam | Java SE, Java…

7/9congdongjava.com/forum/threads/Đa-luông-trong-java-multithreading-in-java.802/

chain-lock để tránh deadlock tốt hơn, … Khi dùng Lock chúng ta nên

theo một template chuẩn như sau:

Lock l = ...;

l.lock();

try {

// Các task truy cập tài nguyên bảo vệ bởi lock đặt ở đây

} finally {

l.unlock();

}

Condition là một interface dùng để nhóm cách xử lý trong các phương

thức (wait, notify, notifyAll) của lớp Object vào thành một đối tượng

nhằm đưa ra nhiều chọn lựa hơn trong việc đồng bộ, ví du�

chúng ta có thê� dùng nhiêu condition và khi nào chúng ta muôn đánh

thức chính xác điều kiện nào được sử dụng tài nguyên.

Ví du� ta dùng la�i ví du� Consumer-Producer ở trên, thêm vào 2 biên

lock, condition và chỉnh sửa hai làm get và put thế là ta cũng được kết

quả như dùng với từ khóa synchronized:

final Lock lock = new ReentrantLock();

final Condition condition = lock.newCondition();

public int get() {

int result;

lock.lock();

try {

while(isRemainingContents == false) {

try {

condition.await();

} catch (InterruptedException e) {

}

}

isRemainingContents = false;

//print onto screen

System.out.println("\tConsumer get " + this.contents);

//get value

result = contents;

//Notify Producer to produce new contents

condition.signalAll();

} finally {

lock.unlock();

}

return result;

}

public void set(int piContents) {

lock.lock();

try {

while(isRemainingContents == true) {

try {

condition.await();

} catch (InterruptedException e) {

}

}

Page 8: Đa luồng trong java (multithreading in Java)

19/07/2012 Đa luông trong java (multithreading in Java) | Cộng đồng Java Việt Nam | Java Việt Nam | Java SE, Java…

8/9congdongjava.com/forum/threads/Đa-luông-trong-java-multithreading-in-java.802/

tranhuyvc, 8/4/10 #1

giant26, 1/1/12 #2

this.contents = piContents;

isRemainingContents = true;

//print onto screen

System.out.println("Producer set " + this.contents);

//Notify Consumer to eat this contents

condition.signalAll();

} finally {

lock.unlock();

}

}

Kêt qua� luôn luôn là thê này:

Producer set 0

Consumer get 0

Producer set 1

Consumer get 1

Producer set 2

Consumer get 2

Producer set 3

Consumer get 3

Producer set 4

Consumer get 4

Producer set 5

Consumer get 5

Producer set 6

Consumer get 6

Producer set 7

Consumer get 7

Producer set 8

Consumer get 8

Producer set 9

Consumer get 9

ConcurrentMap là một interface kế thừa từ Map dùng để cải tiến,

tối ưu hơn khi chạy Map trong ứng dụng đa luồng (multithread)

Ví dụ cách dùng ConcurrentHashMap tương tự dùng Map, tuy nhiên

người ta đã thống kê là nếu chương trình có càng nhiều thread truy

câ�p vào cMap này thì dùng ConcurrentMap se� cho performance tôt

hơn rất nhiều so với dùng Map với đồng bộ kiểu synchronized

public static ConcurrentMap<String,String> cMap =

new ConcurrentHashMap<String, String>(1000);

public static void main(String[] args) {

cMap.putIfAbsent("id", "1");

cMap.putIfAbsent("name", "kien");

cMap.putIfAbsent("email", "[email protected]");

System.out.println(cMap); //Print to screen

}

Kêt qua�: {name=kien, [email protected], id=1}

Ðề: Đa luông trong java (multithreading in Java)

Cho em hỏi sự khác biệt giữa Thread và Runable, khi nào thì sử dụng cái

nào vậy anh?

giant26

Page 9: Đa luồng trong java (multithreading in Java)

19/07/2012 Đa luông trong java (multithreading in Java) | Cộng đồng Java Việt Nam | Java Việt Nam | Java SE, Java…

9/9congdongjava.com/forum/threads/Đa-luông-trong-java-multithreading-in-java.802/

Vietnamese (VI) Liên hệ với Chúng tôiTrang chủ Top

Forum software by XenForo™ ©2011 XenForo Ltd. Điều khoản & Quy định Global Feed

(Bạn phải đăng ký thành viên hoặc đăng nhập vào diễn đàn nếu muốn trả lời bài viết này.)

TweetTweet 0

Chia sẻ trang này

Member

Recommend One person recommends this. Be the first of your friends.

Trang chủ Diễn đàn Bài Viết Hướng Dẫn Bài viết hướng dẫn JSE