線程局部變量的使用


  共享數據是並發程序最核心的問題之一,對於繼承了Thread類或者實現了Runnable接口的對象來說尤其重要。如果創建的對象是實現了Runable接口的類的實例,用它作為傳入參數創建多個線程對象並啟動這些線程,那么所有的線程將共享相同的屬性。也就是說,如果你在一個線程中改變了一個屬性,所有的線程都會被這個改變所影響。

  在某種情況下,這個對象的屬性不需要被所有線程共享。Java並發API提供了一個干凈的機制,即線程局部變量(Thread-Local Variable),其具有很好的性能。示例如下:

import java.util.Date;
import java.util.concurrent.TimeUnit;


public class SafeTask implements Runnable {
    private static ThreadLocal<Date> startDate = new ThreadLocal<Date>(){
        @Override
        protected Date initialValue() {
            return new Date();
        }        
    };
    @Override
    public void run() {
        System.out.printf("Starting Thread: %s : %s\n", Thread.currentThread().getId(), startDate.get());
        try {
            TimeUnit.SECONDS.sleep((int)Math.rint(Math.random()*10));
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.printf("Thread Finished: %s : %s\n", Thread.currentThread().getId(), startDate.get());
    }

    public static void main(String[] args){
        SafeTask st = new SafeTask();
        try {
            for(int i=0;i<10;i++){
                Thread t = new Thread(st);
                t.start();
                TimeUnit.SECONDS.sleep(2);
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

  線程局部變量分別為每個線程存儲了各自的屬性值,並提供給每個線程使用。你可以使用get()方法讀取這個值,並用set()方法設置這個值。如果線程是第一次訪問線程局部變量,線程局部變量可能還沒有為它存儲值,這個時候initialValue()方法就會被調用,並且返回當前的時間值。

  線程局部變量也提供了remove()方法,用來訪問這個變量的線程刪除已經存儲的值。Java並發API包含了InheritableThreadLocal類,如果一個線程是從其他某個線程中創建的,這個類將提供繼承的值。如果一個線程A在線程局部變量已有值,當它創建其它某個線程B時,線程B的線程局部變量將跟線程A是一樣的。你可以覆蓋ChileValue()方法,這個方法用來初始化子線程在線程局部變量中的值。它使用父線程在線程局部變量中的值作為傳入參數。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM