ThreadLocal两个简单示例

tech2022-07-11  160

ThreadLocal作用:

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

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

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

当我们在同一个线程中定义了第二个或多个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); } 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(); } }


最新回复(0)