CyStack logo
  • Sản phẩm & Dịch vụ
  • Giải pháp
  • Bảng giá
  • Công ty
  • Tài liệu
Vi

vi

Trang chủHướng dẫnCác cách tạo thread trong Java
Java

Các cách tạo thread trong Java

CyStack blog 5 phút để đọc
CyStack blog09/08/2025
Locker Avatar

Bao Tran

Web Developer

Locker logo social
Reading Time: 5 minutes

Process và thread là hai đơn vị thực thi cơ bản trong Java. Trong đó chủ đề lập trình đồng thời (concurrency programming) thường quan tâm nhiều hơn đến Thread trong Java.

cách tạo thread trong Java

Process

Một process (tiến trình) là một môi trường thực thi độc lập, có thể được xem như một chương trình hoặc ứng dụng. Tuy nhiên, bản thân một chương trình đó lại có thể chứa nhiều process bên trong.

Môi trường runtime của Java (Java Runtime Environment) chạy dưới dạng một process duy nhất, và process này chứa các class và chương trình khác nhau dưới dạng các process con.

Thread

Thread (luồng) có thể được gọi là một tiến trình nhẹ (lightweight process). Thread cần ít tài nguyên hơn để tạo ra, tồn tại bên trong một process và chia sẻ tài nguyên với process đó.

Mọi ứng dụng Java đều có ít nhất một thread là thread chính (main). Ngoài ra, cũng có nhiều thread khác chạy ngầm như các thread quản lý bộ nhớ, quản lý hệ thống, xử lý tín hiệu… Tuy nhiên, từ góc độ của ứng dụng, main là thread đầu tiên và chúng ta có thể tạo thêm nhiều thread khác từ thread này.

Multithreading (đa luồng) là khái niệm chỉ việc hai hay nhiều thread được thực thi đồng thời trong một chương trình. Bộ xử lý đơn lõi (single core) của máy tính chỉ có thể thực thi một thread tại một thời điểm, và time slicing (chia thời gian) là một tính năng của hệ điều hành (OS) giúp chia sẻ thời gian của bộ xử lý giữa các process và thread khác nhau.

Lợi ích của Thread

  1. Thread nhẹ hơn so với process do việc tạo một thread tốn ít thời gian và tài nguyên hơn.
  2. Các thread có thể chia sẻ dữ liệu và code của process cha.
  3. Việc chuyển đổi ngữ cảnh (context switching) giữa các thread thường ít tốn kém hơn so với giữa các process.
  4. Việc giao tiếp giữa các thread (intercommunication) tương đối dễ dàng hơn so với giao tiếp giữa các process.

Java cung cấp hai cách để tạo một thread bằng code.

  1. Triển khai interface java.lang.Runnable.
  2. Kế thừa class java.lang.Thread.

Ví dụ triển khai interface Runnable

Để một class có thể chạy dưới dạng thread, ta có thể cho nó triển khai interface java.lang.Runnable và cung cấp phần cài đặt trong phương thức run(). Cụ thể, để sử dụng class này như một thread, ta cần tạo một đối tượng Thread mới, truyền vào đối tượng của class đã triển khai Runnable, và sau đó gọi phương thức start() để thực thi phương thức run() trong một thread riêng biệt.

Dưới đây là ví dụ về cách tạo thread trong Java bằng việc triển khai interface Runnable.

package com.journaldev.threads;

public class HeavyWorkRunnable implements Runnable {

    @Override
    public void run() {
        System.out.println("Doing heavy processing - START "+Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
            //Get database connection, delete unused data from DB
            doDBProcessing();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Doing heavy processing - END "+Thread.currentThread().getName());
    }

    private void doDBProcessing() throws InterruptedException {
        Thread.sleep(5000);
    }

}

Ví dụ kế thừa class Thread

Ta có thể kế thừaclass java.lang.Thread để tạo ra một class thread của riêng mình và ghi đè phương thức run(). Sau đó, ta chỉ cần tạo đối tượng của class này và gọi phương thức start() để thực thi phương thức run() của class thread tùy chỉnh.

Dưới đây là một ví dụ đơn giản minh họa cách kế thừa class Thread.

package com.journaldev.threads;

public class MyThread extends Thread {

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

    @Override
    public void run() {
        System.out.println("MyThread - START "+Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
            //Get database connection, delete unused data from DB
            doDBProcessing();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("MyThread - END "+Thread.currentThread().getName());
    }

    private void doDBProcessing() throws InterruptedException {
        Thread.sleep(5000);
    }
    
}

Đây là chương trình kiểm thử minh họa cách tạo và thực thi một java thread.

package com.journaldev.threads;

public class ThreadRunExample {

    public static void main(String[] args){
        Thread t1 = new Thread(new HeavyWorkRunnable(), "t1");
        Thread t2 = new Thread(new HeavyWorkRunnable(), "t2");
        System.out.println("Starting Runnable threads");
        t1.start();
        t2.start();
        System.out.println("Runnable Threads has been started");
        Thread t3 = new MyThread("t3");
        Thread t4 = new MyThread("t4");
        System.out.println("Starting MyThreads");
        t3.start();
        t4.start();
        System.out.println("MyThreads has been started");
        
    }
}

Kết quả của chương trình ví dụ trên là:

Starting Runnable threads
Runnable Threads has been started
Doing heavy processing - START t1
Doing heavy processing - START t2
Starting MyThreads
MyThread - START Thread-0
MyThreads has been started
MyThread - START Thread-1
Doing heavy processing - END t2
MyThread - END Thread-1
MyThread - END Thread-0
Doing heavy processing - END t1

Một khi ta khởi chạy một thread, thứ tự thực thi của nó sẽ phụ thuộc vào cách hệ điều hành triển khai time slicing, và ta không thể kiểm soát được thứ tự này. Mặc dù ta có thể thiết lập độ ưu tiên (priority) cho các thread, điều đó cũng không đảm bảo rằng thread có độ ưu tiên cao hơn sẽ luôn được thực thi trước. Hãy thử chạy chương trình trên nhiều lần và bạn sẽ thấy rằng không có một quy luật nào về thứ tự bắt đầu và kết thúc của các thread.

So sánh Runnable và Thread

Nếu class của bạn cần thực hiện nhiều chức năng khác ngoài việc chạy như một Thread, bạn nên triển khai interface Runnable. Ngược lại, nếu mục đích duy nhất của class chỉ là để chạy như một Thread, bạn có thể kế thừa class Thread.

Việc triển khai Runnable được ưu tiên hơn vì Java cho phép một class triển khai nhiều interface. Trong khi đó, nếu bạn đã kế thừa class Thread, bạn sẽ không thể kế thừa thêm bất kỳ class nào khác.

Chú ý: Như bạn đã thấy, thread không trả về giá trị nào. Nhưng nếu ta muốn thread của mình thực hiện một số xử lý và sau đó trả về kết quả cho chương trình gọi nó thì sao? Hãy xem bài viết về Java Callable và Future của chúng tôi để giải quyết vấn đề này.

Hãy nhớ rằng kể từ Java 8, Runnable đã trở thành một interface hàm, và ta có thể sử dụng biểu thức lambda (lambda expression) để triển khai nó thay vì dùng anonymous class (lớp ẩn danh). Để biết thêm chi tiết, hãy xem bài viết về interface hàm trong Java 8.

Tổng kết

Như vậy, qua bài viết này bạn đã nắm được sự khác biệt giữa process và thread cũng như hai cách tạo thread trong Java. Chúng tôi cũng đã chỉ ra trường hợp nào nên chọn giải pháp nào cho từng bài toán đa luồng. Đừng ngần ngại thử nghiệm với các đoạn code mẫu và hiệu chỉnh chúng cho phù hợp với nhu cầu ứng dụng của bạn.

0 Bình luận

Đăng nhập để thảo luận

Chuyên mục Hướng dẫn

Tổng hợp các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.

Đăng ký nhận bản tin của chúng tôi

Hãy trở thành người nhận được các nội dung hữu ích của CyStack sớm nhất

Xem chính sách của chúng tôi Chính sách bảo mật.

Đăng ký nhận Newsletter

Nhận các nội dung hữu ích mới nhất