ThreadLocal两个简单示例

ThreadLocal作用:

通常我们创建的变量可以被任一个线程访问并修改,如果想实现每一个线程都有自己专属本地变量时,该变量不受其他线程影响,此时可以使用ThreadLocal。

  1. ThreadLocal有三个常用方法,set()、get()、remove()。ThreadLocal<Integer> local = new ThreadLocal<>();

  2. 调用local.set()方法,对当前线程进行赋值。事实上set的值保存在当前线程的ThreadLocalMap中,而不是ThreadLocal中,ThreadLocal可以看作仅对ThreadLocalMap进行了封装,只传递参数,ThreadLocalMap可以看作是为ThreadLocal定制的HashMap。存放时,key就是ThreadLocal对象即这里定义的local,我们添加的变量Integer值作为value来存放。每个线程都有自己的ThreadLocalMap

  3. 当我们在同一个线程中定义了第二个或多个ThreadLocal时,ThreadLocal<Integer> local2 = new ThreadLocal<>(); 接着通过local2.set()进行赋值时,值还会保存到仅有的一个ThreadLocalMap中,而不会再创建一个ThreadLocalMap。源码中是这样,两个ThreadLocal属于同一线程,就直接往map中添加元素,所以只存在一个ThreadLocalMap:在这里插入图片描述

public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }
  1. local.get()、local2.get()分别获取到的是当前线程中我们存放的Integer变量值。

示例1:

使用线程池(顺便学一下线程池的使用哈哈)创建10个线程来存放Integer值 1-10。

public class ThreadLocalTest {
    public static void main(String[] args) throws InterruptedException{
        ThreadLocal<Integer> local = new ThreadLocal<>();

        //创建一个线程池,初始化10个线程,最多15个线程,60SECONDS,多出的线程经过60s没活就回收,
        // 保持10个线程,new LinkedBlockingQueue() 用来放任务的集合
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(10,15,
                60, TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>());

        for (int i = 0; i < 10; i++) {
            int I = i + 1;
            //执行一次为一个线程,执行十次共10个线程
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    local.set(I);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" 的Integer值为:"+ local.get() );

                }
            });

        }
        threadPool.shutdown();
    }
}

在这里插入图片描述


实例2:

public class Person {
    private int age;
    private String name;

    public Person(final int age, final String name) {
        this.age = age;
        this.name = name;
    }

    public int getAge() {
        return this.age;
    }

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

    public String getName() {
        return this.name;
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}
public class ThreadLocalTest1 {
    public static void main(String[] args) {
        ThreadLocal<Person> local = new ThreadLocal<>();
        Person p1 = new Person(23,"张三");
        Person p2 = new Person(45,"李四");
        Person p3 = new Person(76,"王五");
        Person p4 = new Person(98,"赵六");
        ArrayList<Person> list = new ArrayList<>();
        list.add(p1);
        list.add(p2);
        list.add(p3);
        list.add(p4);

        //创建一个线程池,初始化10个线程,最多15个线程,60SECONDS,多出的线程经过60s没活就回收,
        // 保持10个线程,new LinkedBlockingQueue() 用来放任务的集合
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(10,15,
                60, TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>());

        for (int i = 0; i < 4; i++) {
            Person p = list.get(i);
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    local.set(p);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" 的Person为:"+ local.get() );

                }
            });

        }
        threadPool.shutdown();
    }
}

在这里插入图片描述


ThreadLocal是Java中的一个线程局部变量,它提供了一种线程安全的方式来存储每个线程的独立副本。每个线程都可以独立地访问和修改自己的副本,而不会影响其他线程的副本。 ThreadLocal的原理是通过一个ThreadLocalMap来存储每个线程的变量副本。在ThreadLocalMap中,以ThreadLocal对象作为key,以线程的变量副本作为value。当使用ThreadLocal的get()方法获取变量值时,会先获取当前线程,然后从ThreadLocalMap中根据当前ThreadLocal对象获取对应的变量副本。当使用ThreadLocal的set()方法设置变量值时,会先获取当前线程,然后将变量值存储到ThreadLocalMap中对应的位置。 下面是一个简单示例代码,演示了如何使用ThreadLocal来实现线程局部变量: ```java public class ThreadLocalExample { private static ThreadLocal<Integer> threadLocal = new ThreadLocal<>(); public static void main(String[] args) { // 创建并启动两个线程 Thread thread1 = new Thread(() -> { threadLocal.set(1); System.out.println("Thread 1: " + threadLocal.get()); threadLocal.remove(); }); Thread thread2 = new Thread(() -> { threadLocal.set(2); System.out.println("Thread 2: " + threadLocal.get()); threadLocal.remove(); }); thread1.start(); thread2.start(); } } ``` 在上面的代码中,我们创建了一个ThreadLocal对象`threadLocal`,并在两个线程中分别设置和获取变量值。每个线程都有自己独立的变量副本,互不干扰。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值