# Bài 1: Giới thiệu về Fork/Join Framework

#### Định nghĩa và Mục đích

`Fork/Join Framework` là một phần của `java.util.concurrent` được giới thiệu từ Java 7. Nó được thiết kế để giúp các lập trình viên khai thác tối đa sức mạnh của các bộ vi xử lý đa lõi hiện đại bằng cách chia nhỏ các tác vụ lớn thành các tác vụ nhỏ hơn và thực thi chúng song song.

##### Định nghĩa

`Fork/Join Framework` là một framework cho phép chia nhỏ (fork) một tác vụ lớn thành nhiều tác vụ nhỏ hơn và sau đó kết hợp (join) kết quả của các tác vụ nhỏ đó để có kết quả cuối cùng.

##### Mục đích

* **Tận dụng tài nguyên CPU:** Giúp tận dụng tối đa tài nguyên của các bộ vi xử lý đa lõi bằng cách thực thi các tác vụ song song.
    
* **Tối ưu hóa hiệu suất:** Tối ưu hóa thời gian thực thi của các tác vụ phức tạp bằng cách chia nhỏ chúng thành các tác vụ đơn giản hơn và thực thi đồng thời.
    

#### Lợi ích của Fork/Join Framework

##### Tối ưu hóa hiệu suất

`Fork/Join Framework` giúp tối ưu hóa hiệu suất bằng cách chia nhỏ các tác vụ lớn thành các tác vụ nhỏ hơn và thực thi chúng đồng thời. Điều này giúp giảm thời gian thực thi tổng thể của các tác vụ phức tạp.

##### Dễ sử dụng

`Fork/Join Framework` cung cấp một API dễ sử dụng, giúp các lập trình viên dễ dàng chia nhỏ và kết hợp các tác vụ. Bạn chỉ cần kế thừa từ `RecursiveTask` hoặc `RecursiveAction` và triển khai phương thức `compute`.

##### Tích hợp tốt với Java

`Fork/Join Framework` được tích hợp sẵn trong `java.util.concurrent` của Java, giúp dễ dàng sử dụng và tích hợp với các phần khác của ứng dụng Java.

#### Cách thức hoạt động của Fork/Join Framework

##### Quy trình Chia để trị (Divide and Conquer)

`Fork/Join Framework` hoạt động dựa trên nguyên tắc chia để trị (divide and conquer). Quy trình này bao gồm ba bước chính:

1. **Chia (Fork):** Chia tác vụ lớn thành các tác vụ nhỏ hơn.
    
2. **Trị (Compute):** Thực thi các tác vụ nhỏ một cách đồng thời.
    
3. **Kết hợp (Join):** Kết hợp kết quả của các tác vụ nhỏ để có kết quả cuối cùng.
    

##### Work-Stealing Algorithm

`Fork/Join Framework` sử dụng thuật toán Work-Stealing để tối ưu hóa việc phân bổ công việc. Thuật toán này cho phép các thread lấy công việc từ các thread khác khi chúng rảnh rỗi, giúp tối ưu hóa tài nguyên và giảm thời gian chờ đợi.

#### Cách Sử dụng Fork/Join Framework

##### ForkJoinPool

`ForkJoinPool` là lớp trung tâm của `Fork/Join Framework`. Nó quản lý việc thực thi các tác vụ và tối ưu hóa việc phân bổ tài nguyên.

###### Tạo một ForkJoinPool

```java
import java.util.concurrent.ForkJoinPool;

public class ForkJoinPoolExample {
    public static void main(String[] args) {
        ForkJoinPool pool = new ForkJoinPool();
        // Sử dụng pool để thực thi các tác vụ
        pool.shutdown();
    }
}
```

##### ForkJoinTask

`ForkJoinTask` là lớp cơ sở cho các tác vụ trong `Fork/Join Framework`. Nó có hai lớp con chính:

* **RecursiveTask:** Dành cho các tác vụ có trả về kết quả.
    
* **RecursiveAction:** Dành cho các tác vụ không trả về kết quả.
    

###### Sử dụng RecursiveTask

```java
import java.util.concurrent.RecursiveTask;

public class SumTask extends RecursiveTask<Integer> {
    private final int[] array;
    private final int start;
    private final int end;

    public SumTask(int[] array, int start, int end) {
        this.array = array;
        this.start = start;
        this.end = end;
    }

    @Override
    protected Integer compute() {
        if (end - start <= 10) { // Ngưỡng để chia nhỏ tác vụ
            int sum = 0;
            for (int i = start; i < end; i++) {
                sum += array[i];
            }
            return sum;
        } else {
            int mid = (start + end) / 2;
            SumTask leftTask = new SumTask(array, start, mid);
            SumTask rightTask = new SumTask(array, mid, end);
            leftTask.fork(); // Chia nhỏ tác vụ
            int rightResult = rightTask.compute();
            int leftResult = leftTask.join(); // Kết hợp kết quả
            return leftResult + rightResult;
        }
    }
}
```

###### Sử dụng RecursiveAction

```java
import java.util.concurrent.RecursiveAction;

public class PrintTask extends RecursiveAction {
    private final int[] array;
    private final int start;
    private final int end;

    public PrintTask(int[] array, int start, int end) {
        this.array = array;
        this.start = start;
        this.end = end;
    }

    @Override
    protected void compute() {
        if (end - start <= 10) { // Ngưỡng để chia nhỏ tác vụ
            for (int i = start; i < end; i++) {
                System.out.println(array[i]);
            }
        } else {
            int mid = (start + end) / 2;
            PrintTask leftTask = new PrintTask(array, start, mid);
            PrintTask rightTask = new PrintTask(array, mid, end);
            invokeAll(leftTask, rightTask); // Chia nhỏ và thực thi đồng thời
        }
    }
}
```

### Kết Luận

Trong bài viết này, chúng ta đã giới thiệu về `Fork/Join Framework`, một công cụ mạnh mẽ trong Java để xử lý các tác vụ song song. Chúng ta đã tìm hiểu về các khái niệm cơ bản, lợi ích của việc sử dụng `Fork/Join Framework`, và cách thức hoạt động của nó. Chúng ta cũng đã xem qua cách sử dụng `ForkJoinPool`, `RecursiveTask`, và `RecursiveAction`.

### Bài Tập Thực Hành

1. Tạo một `RecursiveTask` để tính tổng các phần tử của một mảng số nguyên.
    
2. Tạo một `RecursiveAction` để in các phần tử của một mảng số nguyên.
    
3. Tối ưu hóa ngưỡng chia nhỏ tác vụ để đạt hiệu suất cao nhất trong ví dụ của bạn.
    

### Lời Khuyên và Best Practices

* **Xác định ngưỡng chia nhỏ phù hợp:** Chọn ngưỡng chia nhỏ phù hợp để tối ưu hóa hiệu suất.
    
* **Sử dụng thuật toán Work-Stealing:** Tận dụng thuật toán Work-Stealing của `Fork/Join Framework` để tối ưu hóa việc phân bổ công việc.
    
* **Quản lý tài nguyên hiệu quả:** Đảm bảo rằng bạn sử dụng `ForkJoinPool` một cách hiệu quả để quản lý tài nguyên hệ thống.
    

Với các kiến thức cơ bản này, bạn sẽ sẵn sàng để đi sâu hơn vào các bài viết tiếp theo trong chuỗi hướng dẫn về `Fork/Join Framework` và khám phá thêm các tính năng và ứng dụng nâng cao của công cụ mạnh mẽ này.
