Sử Dụng Phương Thức Isalive() Và Join()

- Luồng chạy ngầm (deamon): cung cấp các dịch vụ cho các luồng khác. Khi máy ảo Java thực hiện tiến trình thoát, lúc đó chỉ còn duy nhất luồng deamon còn sống. Máy ảo Java có ít nhất một luồng deamon là luồng “garbage collection” (thu lượm tài nguyên

- dọn rác). Luồng dọn rác thực thi chỉ khi hệ thống không có tác vụ nào. Đây là một luồng có quyền ưu tiên thấp. Lớp luồng có hai phương thức để làm việc với luồng deamon:

- public void setDaemon(boolean on)

- public boolean isDaemon()

3.11. Đa luồng và tương tranh

3.11.1.Định nghĩa đa luồng

Là khả năng thực hiện đồng thời nhiều phần khác nhau của một chương trình. Đa luồng quản lý nhiều tác vụ tương tranh, các tác vụ phân biệt dựa trên độ ưu tiên. Hệ thống xử lý đa luồng trong Java được xây dựng trên class Thread và interface Runnable trong packaged java.lang. Sử dụng đa luồng làm tăng quá trình xử lý của các hệ thống xử lý đơn và làm giảm thời gian rỗi của CPU

Ví dụ 3.35: Tạo đa luồng, hiển thị tên của mỗi luồng đang chạy

package test;

public class MultipleThreads extends Thread { String name;

Có thể bạn quan tâm!

Xem toàn bộ 232 trang tài liệu này.

public void run() { while(true) {

name = Thread.currentThread().getName(); System.out.println(name);

try { Thread.sleep(500);

}

catch( InterruptedException e)

{

break;

}

}

}

public static void main(String args[]) { MultipleThreads t1 = new MultipleThreads(); MultipleThreads t2 = new MultipleThreads();

t1.setName(“Thread2”);

t2.setName(“Thread3”); t1.start();

t2.start();

System.out.println(“Number

activeCount());

of

threads running: ” + Thread.

}

}

Kết quả:

Ví dụ 3 36 Tạo 2 luồng public class Thread1 extends Thread Biến lưu tên luồng String 1

Ví dụ 3.36: Tạo 2 luồng

public class Thread1 extends Thread {

/* Biến lưu tên luồng */ String name;

@Override

public void run() {

while(true) {

name = Thread.currentThread().getName(); for (int i=1;i<=5;i++)

{

System.out.println("Thong diep tu luong"+name+" "+i); try

{

Thread.sleep(500);

}

catch( InterruptedException e)

{

break;

}

}}

} }


public class Thread2 extends Thread { String name;

@Override public void run() {

while(true) {

name = Thread.currentThread().getName(); for (int i=1;i<=5;i++)

{

System.out.println("Thong diep tu luong"+name+" "+i); try

{

Thread.sleep(500);

}


catch( InterruptedException e)

{

break;

}


}

}


public class Test {

public static void main(String[] args) { Thread1 t1 = new Thread1();

Thread2 t2 = new Thread2(); t1.setName("Thread1");

t2.setName("Thread2"); t1.start();

t2.start();

System.out.println("Number of threads running:"+ Thread. activeCount());

}


}

Kết quả: số luồng đang chạy là 3, vì thêm một luồng chạy ngầm mặc định

3 11 2 Sử dụng phương thức isAlive và join Một luồng được xem là alive khi đang 2

3.11.2.Sử dụng phương thức isAlive() và join()

Một luồng được xem là alive khi đang chạy.

Cú pháp: public final boolean isAlive()

Ví dụ 3.37:

public static void main(String [] args)

{

ThreadDemo Obj = new ThreadDemo(); Thread t = new Thread(Obj);

System.out.println(“The thread is alive :” + t.isAlive());

}

public final void join(long millis) throws InterruptedException

public final void join(long millis, int nanos) throws InterruptedException

public final void join() throws InterruptedException

Đây là phương thức được gọi bởi một thread khác.

- Phương thức này làm cho thread gọi phải ngưng hoạt động và chờ trong một khoảng thời gian millis millisecond hoặc chờ trong khoảng thời gian millis millisecond và nanos nanosseconds, hoặc chờ cho đến khi thread này kết thúc thì mới tiếp tục hoạt động.

- Phương thức này có thể phát sinh một ngoại lệ InterruptedException nếu nó bị một thread khác làm ngưng hoạt động.

Ví dụ 3.38:

try

{

System.out.println(“I am in the main and waiting for the thread to

finish”);

// objTh is a Thread object objTh.join();

}

catch( InterruptedException e)

{

System.out.println(“Main thread is interrupted”);

}

3.11.3.Điều kiện tương tranh và cách khắc phục

3.11.3.1. Điều kiện tương tranh

- Khi tạo ra nhiều thread hoạt động song song độc lập (tức là không có dữ liệu chia sẻ) thì không xảy ra vấn đề gì.

- Tuy nhiên khi hai hay nhiều thread cùng sử dụng chung một biến hay một phương thức thì : vì các thread trong một Process có thể được thực thi đồng thời (hệ thống nhiều CPU) hoặc được luân phiên gọi trong một thời gian rất ngắn (hệ thống đơn CPU) việc sử dụng dữ liệu chia sẻ là gần như đồng thời. Điều này dẫn đến vấn về Race condition.

- Race condition (điều kiện tranh chấp) : xảy ra khi có hai hay nhiều thread cùng chia sẻ dữ liệu, khi chúng cùng đọc, cùng ghi dữ liệu chia sẻ đó đồng thời. Kết quả nhận được sẽ phụ thuộc vào tác động lên biến chia sẻ là gì và lúc nào. Và người lập trình không thể biết được chính xác điều gì xảy ra.

3.11.3.2. Khắc phục

Trong Java không có biến toàn cục, chỉ có thuộc tính của đối tượng, tất cả các thao tác có thể dẫn đến hỏng hóc đều thực hiện qua phương thức, do vậy Java cung cấp từ khoá synchronized sử dụng cho phương thức hay đoạn mã cần bảo vệ, từ khoá này được thêm vào định nghĩa của phương thức báo cho Java biết đây là một phương thức đồng bộ, mỗi đối tượng sẽ có một bộ khóa quản lý, bộ khóa quản lý này chỉ cho 1 phương thức synchronized của đối tượng đó chạy tại một thời điểm

Khai báo như sau :

public synchronized void protectedMethod(object obj)

- Method protectedMethod sẽ được đảm bảo thực thi tuần tự.

- Nghĩa là khi có 2 thread A và B gọi method protectedMethod thì nếu method A gọi trước thì chỉ khi nào method protectedMethod thực thi xong thì thread B mới được gọi. Và trong thời gian đó thì thread B phải chờ.

Mấu chốt của sự đồng bộ hóa là khái niệm “monitor” (giám sát), hay còn gọi “semaphore” (cờ hiệu). Một “monitor” là một đối tượng có khóa độc quyền. Chỉ một luồng có thể có monitor tại mỗi thời điểm. Tất cả các luồng khác cố gắng thâm nhập vào

monitor sẽ bị trì hoãn, cho đến khi luồng đầu tiên thoát khỏi monitor. Các luồng khác được báo chờ đợi monitor. Một luồng có thể monitor một đối tượng nhiều lần.

3.11.4.Cách sử dụng phương thức wait() và notify()

Java cung cấp cơ chế giao tiếp liên-quá trình bằng cách sử dụng phương thức wait(), notify() notifyAll().

Các phương thức wait(), notify() and notifyAll() chỉ được gọi từ bên trong một phương thức được đồng bộ hóa (synchronized method).

public final void wait() throws InterruptException

Đặt luồng vào trạng thái chờ (sleeping) một luồng khác, cho đến khi có một luồng khác thông báo notify() thì nó lại tiếp tục, đây là phương thức của lớp cơ sở Object

public final void notify () Đánh thức luồng đầu tiên đang ở trạng thái sleeping

public final void notifyAll() đánh thức tất cả các luồng đang ở trạng thái sleeping.

Khi tất cả các luồng thoát khỏi trạng thái sleeping, luồng có độ ưu tiên cao nhất sẽ chạy đầu tiên.

Ví dụ 3.39:

package thread.relationship; public class Customer {

private int balance = 1000; public Customer() {

System.out.println("Tai khoan cua ban la " + balance);

}

private synchronized void withdraw(int amount) { System.out.println("Giao dich rut tien dang thuc hien " + amount + " ");

if(balance < amount) { System.out.println("Cannot withdraw!"); try {

wait();

} catch (InterruptedException ie) { System.out.println(ie.toString());

}

}

balance -= amount;

System.out.println("Rut tien thanh cong. Tai khoan hien tai cua ban la " +

balance);

}

private synchronized void deposit(int amount) { System.out.println("Giao dich nap tien " + amount + ""); balance += amount;

System.out.println("Nap tien thanh cong. Tai khoan hien tai cua ban la " + balance);

notify();

}

public static void main(String[] args) { Customer c = new Customer();

Thread t1 = new Thread(){ public void run() {

c.withdraw(2000);

}

};

t1.start();


Thread t2 = new Thread(){ public void run() {

c.deposit(3000);

}

};

t2.start();

}

}

3.11.5.Định nghĩa deadlock và khắc phục

Deadlock mô tả tình huống mà hai hoặc nhiều luồng bị chặn mãi mãi, chờ đợi luồng khác giải phóng tài nguyên.

Đôi khi, xảy ra khi hai luồng bị khóa không được dùng tài nguyên tương ứng của chúng, và phải đợi mở khóa để thực hiện trao đổi tài nguyên.

Trong tình huống đó, trạng thái chờ sẽ xảy ra mãi mãi vì cả hai đều đang trong trạng thái lẫn lộn: luồng nào sẽ rời khỏi khóa và luồng nào sẽ đi vào vùng tài nguyên.

Đây là tình trạng tắc nghẽn (deadlock) luồng trong Java. Tình trạng bế tắc khiến việc thực thi chương trình bị dừng lại.

Ví dụ 3.40: Minh hoạ deadlock

public class DeadlockDemo implements Runnable

{


public static void main(String args[])

{

DeadlockDemo objDead1 = new DeadlockDemo(); DeadlockDemo objDead2 = new DeadlockDemo(); Thread objTh1 = new Thread (objDead1); Thread objTh2 = new Thread (objDead2); objDead1.grabIt = objDead2;

objDead2.grabIt = objDead1; objTh1.start();

objTh2.start(); System.out.println(“Started”); try {

objTh1.join(); objTh2.join();

} catch( InterruptedException e)

{


System.out.println(“error occurred”);

} System.exit(0

}

DeadlockDemo grabIt;

public synchronized void run() {


try {

Thread.sleep(500);


} catch( InterruptedException e)

{ System.out.println(“error occurred”);

}

grabIt.syncIt(); }

public synchronized void syncIt() { try {

Thread.sleep(500);

System.out.println(“Sync”);

..... Xem trang tiếp theo?
⇦ Trang trước - Trang tiếp theo ⇨

Ngày đăng: 29/01/2024