ThreadLocal模式探索

一、首先,ThreadLocal模式使共享数据能多个线程被访问,每个线程访问的只是这个数据的副本,线程之间互不影响。

  例子1:

package Thread2;

public class Counter {

    //新建一个静态的ThreadLocal变量,并通过get方法将其变为一个可访问的对象
    private static ThreadLocal<Integer> counterContext = new ThreadLocal<Integer>(){
        protected synchronized Integer initialValue(){
            return 10;
        }
    };
    
    //通过静态的get方法访问ThreadLocal中存储的值
    public static Integer get(){
        return counterContext.get();
    }
    
    //通过静态的set方法将变量值设置到ThreadLocal中
    public static void set (Integer value){
        counterContext.set(value);
    }
    //封装业务逻辑,操作存储于ThreadLocal中的变量
    public static Integer getNextCounter(){
        counterContext.set(counterContext.get()+1);
        return counterContext.get();
    }
}
package Thread2;

public class ThreadLocalTest extends Thread {

    public void run(){
        
        for(int i = 0; i < 3; i ++){
            System.out.println("Thread[" + Thread.currentThread().getName() + " ], "
                    + "counter = " + Counter.getNextCounter());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    
}
package Thread2;

public class Test2 {

    public static void main(String[] args) throws Exception{
        
        ThreadLocalTest testThread1 = new ThreadLocalTest();
        ThreadLocalTest testThread2 = new ThreadLocalTest();
        ThreadLocalTest testThread3 = new ThreadLocalTest();
        
        testThread1.start();
        testThread2.start();
        testThread3.start();
    }
}

运行结果:

Thread[Thread-2 ], counter = 11
Thread[Thread-0 ], counter = 11
Thread[Thread-1 ], counter = 11
Thread[Thread-1 ], counter = 12
Thread[Thread-2 ], counter = 12
Thread[Thread-0 ], counter = 12
Thread[Thread-2 ], counter = 13
Thread[Thread-1 ], counter = 13
Thread[Thread-0 ], counter = 13

例子2:

package Thread;

class AStub {
    public void output() {
        LocalThreadScopeData data = LocalThreadScopeData.getInstance();
        if (data != null)
            System.out.println("AStub:" + Thread.currentThread().getName()
                    + ": data name = " + data.getName() + "age= "
                    + data.getAge());
    }
}

package Thread;

class BStub {
    public void output() {
        LocalThreadScopeData data = LocalThreadScopeData.getInstance();
        if (data != null)
            System.out.println("BStub:" + Thread.currentThread().getName()
                    + ": data name = " + data.getName() + "age= "
                    + data.getAge());
    }
}



package Thread;

class LocalThreadScopeData {
    // 把对象与当前线程绑定
    private static ThreadLocal<LocalThreadScopeData> mThreadLocal = new ThreadLocal<LocalThreadScopeData>();
    // 当前实例
    private static LocalThreadScopeData instance = null;

    // 单例模式
    public static LocalThreadScopeData getInstance() {
        instance = mThreadLocal.get();
        if (instance == null) {
            instance = new LocalThreadScopeData();
            mThreadLocal.set(instance);
        }
        return instance;
    }

    private String name;// 姓名
    private Integer age;// 年龄

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}


package Thread;
import java.util.Random;

public class ThreadTest {

    public static void main(String argv[]) {

        // 启动俩个线程
        for (int i = 0; i < 2; i++) {

            new Thread() {
                
                public void run() {
                    int value = new Random().nextInt(10);
                    LocalThreadScopeData data = LocalThreadScopeData
                            .getInstance();
                    data.setAge(value);
                    data.setName("name" + value);
                    System.out.println("main:" + Thread.currentThread().getName()
                            + "name = name " + value);
                    
                    try {
                    Thread.sleep(1000);
                    } catch (InterruptedException e) {
                    }
                    new AStub().output();
                    new BStub().output();
                }
            }.start();
        }
    }
}

运行结果:

main:Thread-0name = name 5
main:Thread-1name = name 0
AStub:Thread-0: data name = nullage= null
AStub:Thread-1: data name = name0age= 5
BStub:Thread-0: data name = nullage= null
BStub:Thread-1: data name = name0age= 5

例子3:

package Thread4;

public class Student {
    private int age = 0;   //年龄
 
    public int getAge() {
        return this.age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
}

package Thread4;

import java.util.Random;

public class ThreadLocalDemo implements Runnable {
    //创建线程局部变量studentLocal,在后面你会发现用来保存Student对象
    private final static ThreadLocal studentLocal = new ThreadLocal();
 
    public static void main(String[] agrs) {
        ThreadLocalDemo td = new ThreadLocalDemo();
        Thread t1 = new Thread(td, "a");
        Thread t2 = new Thread(td, "b");
        t1.start();
        t2.start();
    }
 
    public void run() {
        accessStudent();
    }
 
    /**
     * 示例业务方法,用来测试
     */
    public void accessStudent() {
        //获取当前线程的名字
        String currentThreadName = Thread.currentThread().getName();
        System.out.println(currentThreadName + " is running!");
        //产生一个随机数并打印
        Random random = new Random();
        int age = random.nextInt(100);
        System.out.println("thread " + currentThreadName + " set age to:" + age);
        //获取一个Student对象,并将随机数年龄插入到对象属性中
        Student student = getStudent();
        student.setAge(age);
        System.out.println("thread " + currentThreadName + " first read age is:" + student.getAge());
        try {
            Thread.sleep(500);
        }
        catch (InterruptedException ex) {
            ex.printStackTrace();
        }
        System.out.println("thread " + currentThreadName + " second read age is:" + student.getAge());
    }
 
    protected Student getStudent() {
        //获取本地线程变量并强制转换为Student类型
        Student student = (Student) studentLocal.get();
        //线程首次执行此方法的时候,studentLocal.get()肯定为null
        if (student == null) {
            //创建一个Student对象,并保存到本地线程变量studentLocal中
            student = new Student();
            studentLocal.set(student);
        }
        return student;
    }
}

运行结果:

b is running!
thread b set age to:31
a is running!
thread a set age to:45
thread b first read age is:31
thread a first read age is:45
thread b second read age is:31
thread a second read age is:45

参考:struts2设计模式,

http://lavasoft.blog.51cto.com/62575/51926/

http://blog.csdn.net/com360/article/details/6789367

  

原文地址:https://www.cnblogs.com/mynona/p/3393223.html