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

Mục lục

Trang chủBlogSử dụng ThreadLocal trong...
Java

Sử dụng ThreadLocal trong Java để tạo biến cục bộ

3 phút đọc30/07/2025
CyStack Author
Bao Tran

Web Developer

0 lượt xem
Reading Time: 3 minutes

ThreadLocal trong Java được dùng để tạo ra các biến cục bộ của luồng (thread local variables). Ta biết rằng tất cả các thread của một Object đều chia sẻ chung biến, do đó biến không đảm bảo an toàn đa luồng (thread safe). Ta có thể dùng cơ chế đồng bộ (synchronization) để đảm bảo an toàn cho thread. Nhưng nếu muốn tránh giải pháp đó, ta có thể sử dụng ThreadLocal.

ThreadLocal trong Java

Java ThreadLocal

Mỗi thread sẽ có biến ThreadLocal riêng, và có thể dùng các phương thức get()set() để lấy giá trị mặc định hoặc thay đổi giá trị của biến đó trong phạm vi thread của mình. Các thực thể ThreadLocal thường là các trường mang tính private static trong những class muốn gắn trạng thái với một thread.

Ví dụ ThreadLocal

Đây là một ví dụ nhỏ minh họa cách sử dụng ThreadLocal trong Java và chứng minh rằng mỗi thread có một bản sao riêng của biến ThreadLocal.

File ThreadLocalExample.java:

package com.journaldev.threads;

import java.text.SimpleDateFormat;
import java.util.Random;

public class ThreadLocalExample implements Runnable{

    // SimpleDateFormat is not thread-safe, so give one to each thread
    private static final ThreadLocal formatter = new ThreadLocal(){
        @Override
        protected SimpleDateFormat initialValue()
        {
            return new SimpleDateFormat("yyyyMMdd HHmm");
        }
    };
    
    public static void main(String[] args) throws InterruptedException {
        ThreadLocalExample obj = new ThreadLocalExample();
        for(int i=0 ; i<10; i++){
            Thread t = new Thread(obj, ""+i);
            Thread.sleep(new Random().nextInt(1000));
            t.start();
        }
    }

    @Override
    public void run() {
        System.out.println("Thread Name= "+Thread.currentThread().getName()+" default Formatter = "+formatter.get().toPattern());
        try {
            Thread.sleep(new Random().nextInt(1000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //formatter pattern is changed here by thread, but it won't reflect to other threads
        formatter.set(new SimpleDateFormat());
        
        System.out.println("Thread Name= "+Thread.currentThread().getName()+" formatter = "+formatter.get().toPattern());
    }

}

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

Thread Name= 0 default Formatter = yyyyMMdd HHmm
Thread Name= 1 default Formatter = yyyyMMdd HHmm
Thread Name= 0 formatter = M/d/yy h:mm a
Thread Name= 2 default Formatter = yyyyMMdd HHmm
Thread Name= 1 formatter = M/d/yy h:mm a
Thread Name= 3 default Formatter = yyyyMMdd HHmm
Thread Name= 4 default Formatter = yyyyMMdd HHmm
Thread Name= 4 formatter = M/d/yy h:mm a
Thread Name= 5 default Formatter = yyyyMMdd HHmm
Thread Name= 2 formatter = M/d/yy h:mm a
Thread Name= 3 formatter = M/d/yy h:mm a
Thread Name= 6 default Formatter = yyyyMMdd HHmm
Thread Name= 5 formatter = M/d/yy h:mm a
Thread Name= 6 formatter = M/d/yy h:mm a
Thread Name= 7 default Formatter = yyyyMMdd HHmm
Thread Name= 8 default Formatter = yyyyMMdd HHmm
Thread Name= 8 formatter = M/d/yy h:mm a
Thread Name= 7 formatter = M/d/yy h:mm a
Thread Name= 9 default Formatter = yyyyMMdd HHmm
Thread Name= 9 formatter = M/d/yy h:mm a

Từ kết quả, ta có thể thấy Thread-0 đã thay đổi giá trị của formatter, nhưng formatter của thread-2 vẫn giữ nguyên giá trị khởi tạo. Ta cũng thấy điều tương tự xảy ra với các thread khác.

Class ThreadLocal trong Java 8 đã được mở rộng với một phương thức mới withInitial(). Nó nhận interface hàm Supplier làm tham số. Do đó, ta có thể dùng biểu thức lambda để tạo thực thể ThreadLocal một cách dễ dàng. Ví dụ, biến ThreadLocal tên formatter ở trên có thể được định nghĩa chỉ trong một dòng như sau:

private static final ThreadLocal formatter = 
	ThreadLocal.withInitial
	(() -> {return new SimpleDateFormat("yyyyMMdd HHmm");});

Tổng kết

Nếu bạn quan tâm hơn về chi tiết của ThreadLocal, hãy xem thêm tài liệu chính thức để nắm rõ từng phương thức và ứng dụng thực tế. Ngoài ra, bạn cũng có thể khám phá các bài viết khác về Java 8 trên blog này, nhất là chủ đề về interface hàm.

Về tác giả

Bao Tran
Bao TranWeb Developer

I’m passionate about web development and sharing my insights through articles, with over 8 years of experience. I hope these sharings inspire you and help build a strong web development community. @#@ Tôi đam mê phát triển web và chia sẻ những hiểu biết của mình thông qua các bài viết, với hơn 8 năm kinh nghiệm. Tôi hy vọng những chia sẻ này sẽ truyền cảm hứng cho các bạn và giúp xây dựng một cộng đồng phát triển web mạnh mẽ.

Cập nhật thông tin mới nhấtNhận các thông tin mới nhất về mối đe dọa, báo cáo an ninh mạng từ CyStack về hòm thư điện tử của bạn

Thảo luận (0)

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

Bài viết liên quan