Đa luồng trong java (Bài 7 ) | Gia Sư Tin Học

Đa luồng trong java sẽ đề cập đến hai khái niệm Multitasking và Multithreading

Multitasking : Là năng lực chạy đồng thời một hoặc nhiều chương trình cùng một lúc trên một hệ điều hành quản lý. Hệ điều hành quản trị việc này và sắp xếp lịch tương thích cho những chương trình đó. Ví dụ, trên hệ quản lý Windows tất cả chúng ta có thao tác đồng thời với những chương trình khác nhau như : Microsoft Word, Google Chrome, …

Multithreading:
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 được gọi là thread. Ví dụ trong Microsoft Excel chúng ta có thể
làm việc đồng thời với các sheet khác nhau

Đa luồng trong java – Thread ?

Thread là đơn vị nhỏ nhất của mã thực thi mà đoạn mã đó thực hiện một nhiệm vụ cụ thể.

Một ứng dụng có thể được chia nhỏ thành nhiều nhiệm vụ và mỗi nhiệm vụ có thể được giao cho một thread.

Nhiều thread cùng thực hiện đồng thời được gọi là đa luồng (multithread). Các quá trình đang chạy dường như là đồng thời, nhưng thực ra nó không phải là như vậy.

Vòng đời của một thread

da luong trong java 1

Đa luồng trong java – Các trạng thái của thread

da luong trong java 2da luong trong java 3da luong trong java 4

Đa luồng trong java – Khởi tạo thread

Hệ thống giải quyết và xử lý đa luồng trong Java được kiến thiết xây dựng trên class Thread và interface Runnable trong packaged java.lang .

Cách 1: Tạo thread bằng cách sử dụng interface Runnable

  1. Viết 1 class thực thi interface Runnable và viết lại phương thức  public void run()
  2. Tạo ra 1 object vừa thực thi interface Runnable.
  3. Tạo ra 1 object của class Thread với tham số truyền vào là object thực thi interface Runable.
  4. Gọi phương thức start() để chạy thread

Ví dụ tạo thread bằng cách sử dụng interface Runnable

package thread;
/**
 *
 * @author giasutinhoc.vn
 */
public class FirstThread implements Runnable {

    @Override
    public void run() {
        for (int i = 1; i <= 5; i++) {
            System.out.println("Thong diep tu thread dau tien: " + i);
            try {                
                Thread.sleep(1000);
            } catch (InterruptedException ie) {
                System.err.println(ie.toString());
            }
        }
    }    
}
package thread;
/**
 *
 * @author giasutinhoc.vn
 */
public class SecondThread implements Runnable {

    @Override
    public void run() {
        for (int i = 1; i <= 5; i++) {
            System.out.println("Thong diep tu thread thu hai: " + i);
            try {                
                Thread.sleep(1000);
            } catch (InterruptedException ie) {
                System.err.println(ie.toString());
            }
        }
    }    
}
package thread;
/**
 *
 * @author giasutinhoc.vn
 */
public class ThreadDemo {

    public static void main(String[] args) {
        //Tao doi tuong
        FirstThread ft = new FirstThread();
        SecondThread st = new SecondThread();
        
        //Bat dau thread thu nhat
        Thread t1 = new Thread(ft);
        t1.start();
        
        //Bat dau thread thu hai
        Thread t2 = new Thread(st);
        t2.start();
        
    }
}

Khi chạy chương trình trên, tất cả chúng ta sẽ nhận được tác dụng sau

Cách 2: Tạo thread bằng cách kế thừa từ lớp Thread

  1. Tạo một lớp kế thừa từ lớp Thread và viết lại (override) phương thức run()
  2. Tạo ra một đối tượng của lớp vừa kế thừa từ lớp Thread
  3. Gọi phương thức start() để chạy thread

Ví dụ tạo thread bằng cách thừa kế từ lớp Thread

package thread;
/**
 *
 * @author giasutinhoc.vn
 */
public class ThreeThread extends Thread {

    public ThreeThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i = 1; i <= 5; i++) {
            System.out.println(i + " " + getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ie) {
                System.err.println(ie.toString());
            }
        }

        System.out.println(getName() + " da hoan thanh!");
    }
    
    public static void main(String[] args) {
        ThreeThread tt1 = new ThreeThread("Tp. Ho Chi Minh");
        ThreeThread tt2 = new ThreeThread("Tp. Can Tho");
        tt1.start();
        tt2.start();
    }
}

Khi chạy chương trình trên, tất cả chúng ta sẽ nhận được tác dụng sau

Ví dụ thực hiện 1 công việc bằng nhiều Thread

package thread;
/**
 *
 * @author giasutinhoc.vn
 */
public class OneTaskUsingMultiThread implements Runnable {

    @Override
    public void run() {
        System.out.println("Xu ly mot tac vu su dung nhieu thread");
    }
    
    public static void main(String[] args) {        
        Thread t1 = new Thread(new OneTaskUsingMultiThread());
        Thread t2 = new Thread(new OneTaskUsingMultiThread());
        t1.start();
        t2.start();
    }
}

Ngoài ra, tất cả chúng ta hoàn toàn có thể sử dụng cách thừa kế từ class Thread để thực thi nhu yếu này

Ví dụ thực hiện nhiều công việc sử dụng nhiều Thread

package thread;
/**
 *
 * @author giasutinhoc.vn
 */
public class MultiTaskUsingMultiThread1 extends Thread {

    @Override
    public void run() {
        System.out.println("Task 1");
    }
    
}
package thread;
/**
 *
 * @author giasutinhoc.vn
 */
public class MultiTaskUsingMultiThread2 extends Thread{
    
    @Override
    public void run() {
        System.out.println("Task 2");
    }
}
package thread;
/**
 *
 * @author giasutinhoc.vn
 */
public class MultiTaskUsingMultiThreadDemo {
    public static void main(String[] args) {
        MultiTaskUsingMultiThread1 task1 = new MultiTaskUsingMultiThread1();
        MultiTaskUsingMultiThread2 task2 = new MultiTaskUsingMultiThread2();
        task1.start();
        task2.start();
    }
}

Đa luồng trong java – Sự khác nhau giữa cài đặt Runnable và kế thừa Thread

package thread;
/**
 *
 * @author giasutinhoc.vn
 */
public class UsingThread extends Thread{
    private int cnt = 0;
    @Override
    public void run() {
        cnt++;
        System.out.println("Tao thread su dung tu khoa extends: " + cnt);
    }    
}
package thread;
/**
 *
 * @author giasutinhoc.vn
 */
public class UsingRunnable implements Runnable {
    private int cnt = 0;
    @Override
    public void run() {
        cnt++;
        System.out.println("Tao thread su dung tu khoa implements: " + cnt);
    }
}
package thread;
/**
 *
 * @author giasutinhoc.vn
 */
public class DifferenceBetweenDemo {
    public static void main(String[] args) throws InterruptedException {
        //Nhiều đối tượng thread
        UsingRunnable ur = new UsingRunnable();
        Thread t1 = new Thread(ur);
        t1.start();
        Thread.sleep(1000);
        Thread t2 = new Thread(ur);
        t2.start();
        Thread.sleep(1000);
        
        //Mỗi thread tương ứng với một thể hiện
        UsingThread ut1 = new UsingThread();
        ut1.start();
        Thread.sleep(1000);
        UsingThread ut2 = new UsingThread();
        ut2.start();        
    }
}

Khi chạy chương trình trên, tất cả chúng ta sẽ nhận được hiệu quả sau
da luong trong java 8

Đa luồng trong java – Quản lý thread

Thứ tự ưu tiên giữa các thread

Phương thức join(): Thiết lập một thread phải chờ cho đến khi một thread khác hoạt động xong

package thread;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
 *
 * @author giasutinhoc.vn
 */
public class UsingJoinMethod extends Thread {
    
    public UsingJoinMethod(String name) {
        super(name);        
    }
    @Override
    public void run() {
        System.out.println(getName());
        for(int i = 1; i <=5; i++) {
            try {
                System.out.print(i + " ");
                Thread.sleep(500);
            } catch (InterruptedException ie) {
                System.out.println(ie.toString());
            }
        }
        System.out.println();
    }    
    
    public static void main(String[] args) {
        UsingJoinMethod t1 = new UsingJoinMethod("Thread 1");
        UsingJoinMethod t2 = new UsingJoinMethod("Thread 2");
        t1.start();
        try {
            t1.join();
        } catch (InterruptedException ie) {
            System.err.println(ie.toString());
        }
        t2.start();
    }
}

Khi chạy chương trình trên, tất cả chúng ta sẽ nhận được tác dụng sau

Đồng bộ hóa giữa các thread

Đồng bộ hóa chính là việc sắp xếp thứ tự các luồng khi truy xuất vào cùng đối tượng sao cho không có sự xung đột dữ liệu.

Để đảm bảo rằng một nguồn tài nguyên chia sẻ được sử dụng bởi một thread tại một thời điểm, chúng ta sử dụng đồng bộ hóa (synchronization).

Mối quan hệ giữa các thead

Java cũng 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).

Ví dụ về mối quan hệ giữa các thread

package thread.relationship;
/**
 *
 * @author giasutinhoc.vn
 */
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();
    }
}

Khi chạy chương trình trên, tất cả chúng ta sẽ nhận được tác dụng sau

Đa luồng trong java – Tổng kết

  • Khái niệm multitasking và multithreading
  • Khái niệm ‘thread’ – luồng
  • Các trạng thái của thread
  • Khởi tạo thread
  • Quản lý thread