从头认识多线程-4.2 对象逸出的其余解决方案-主要是ThreadLocal的应用
这一章节我们来讨论一下对象逸出的其他解决方案。
1.由于出现对象逸出都是在多线程环境下,那么,我们换成单线程即可,当然,这个方法基本没有人使用, 因为现在都是多核处理器,为了提升性能,不可能使用单核,但是下面我也给出例子吧。
package com.ray.deepintothread.ch04.topic_2; public class Ad_hoc { private int id = 0; public int getId() { return id; } public void setId(int id) { this.id = id; } public void addId() { id++; } public static void main(String[] args) { Ad_hoc ad_hoc = new Ad_hoc(); for (int i = 0; i < 10; i++) { ad_hoc.addId(); System.out.println(ad_hoc.getId()); } for (int i = 0; i < 10; i++) { ad_hoc.setId(i); System.out.println(ad_hoc.getId()); } } }
2.栈封闭
其实就是把全局变量变成局部变量,在多线程环境下,只能够在独立线程里面访问或引用
package com.ray.deepintothread.ch04.topic_2; import java.util.HashSet; public class CloseStack extends Thread{ public static void test() { HashSet<String> set = new HashSet<>(); for (int i = 0; i < 10; i++) { set.add(i + ""); } } @Override public void run() { test(); } public static void main(String[] args) { new CloseStack().start(); new CloseStack().start(); new CloseStack().start(); } }
3.使用ThreadLocal
ThreadLocal把相应的属性域赋值一份,线程读写的都只是属性域的副本。
package com.ray.deepintothread.ch04.topic_2; public class ThreadLocalTest extends Thread { private int count = 0; public ThreadLocal<Integer> intThreadLocal = new ThreadLocal<Integer>() { protected Integer initialValue() { return count; }; }; public int getCount() { return intThreadLocal.get(); } public void addCount() { intThreadLocal.set(count++); } @Override public void run() { try { for (int i = 0; i < 3; i++) { addCount(); System.out.println("Thread[" + getName() + "] count[" + getCount() + "]"); sleep(50); } } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) throws InterruptedException { new ThreadLocalTest().start(); Thread.sleep(100); new ThreadLocalTest().start(); Thread.sleep(100); new ThreadLocalTest().start(); } }输出:
Thread[Thread-0] count[0]
Thread[Thread-0] count[1]
Thread[Thread-1] count[0]
Thread[Thread-0] count[2]
Thread[Thread-1] count[1]
Thread[Thread-2] count[0]
Thread[Thread-1] count[2]
Thread[Thread-2] count[1]
Thread[Thread-2] count[2]
从输出可以看见,每一个线程都是单独读写工作内存里面的属性副本。
但是,这里会出现一个问题,如果这个属性域是每一个线程都需要更新状态的呢?这个时候必须同步,下面的章节会有想要的对比,这一章节就不展开。
总结:这一章节我们讨论了对象逸出的其他解决方案-主要是ThreadLocal的应用。
这一章节就到这里,谢谢
------------------------------------------------------------------------------------
我的github:https://github.com/raylee2015/DeepIntoThread
目录:http://blog.****.net/raylee2007/article/details/51204573