Java多线程基础(三)

来源:互联网 发布:淘宝助理手机详情 编辑:程序博客网 时间:2024/06/13 22:32

java多线程基础(三)–回顾学习历程,由浅及深,作为个人笔记,也希望帮到需要的人
6、高级多线程控制类:
java.util.concurrent提供许多高级多线程工具类。这里说明一下,并发指通过线程的切换交替执行不同的任务,同一时刻只执行一个任务,而并行则是真正的实时执行多个任务。
(1)ThreadLocal
ThreadLocal类,作用是为当前线程提供线程内的局部变量,使线程随时可以获取到自己存入的值,达到线程之间隔离的效果。

//2个线程共用一个gen变量,执行结果为各自产生seqNum,互不干扰//使用方法如下:定义和初始化ThreadLocal,调用set()方法为ThreadLocal存入的变量设值,调用get()方法从ThreadLocal取值//为了防止潜在的内存泄漏,最好显式调用remove()清理ThreadLocal内的valuepublic class ConcurrentTest {    public static void main(String[] args) {        SeqGenerator gen = new SeqGenerator();        new PrintSeqNumThread(gen).start();        new PrintSeqNumThread(gen).start();    }}class SeqGenerator {    private static ThreadLocal<Integer> seqNum = new ThreadLocal<Integer>() {        @Override        public Integer initialValue() {            return 0;        }    };    public int next() {        seqNum.set(seqNum.get() + 1);        return seqNum.get();    }}class PrintSeqNumThread extends Thread {    private SeqGenerator gen;    PrintSeqNumThread(SeqGenerator gen) {        this.gen = gen;    }    @Override    public void run() {        for (int i = 0 ; i < 3; i ++) {            System.out.println(Thread.currentThread().getName() + ": " + gen.next());        }    }}

简单讲一下ThreadLocal的实现原理:ThreadLocal维护一个索引,指向一个ThreadLocalMap,该map由具体的Thread持有,key为ThreadLocal的引用。设值时,具体的线程将变量value存储到该map,取值从该map取出。从而实现无论何时何地,线程都可以取到它自己设值的变量。
关于内存泄漏的可能性:由于ThreadLocalMap的key使用的是ThreadLocal的弱引用(key -> ThreadLocal),当不存在强引用指向ThreadLocal时,ThreadLocal可能被回收,导致key为null,而value在线程活动时存在一条强引用链(Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value),不会被回收。虽然java有防范措施,在一定的条件下能够主动擦除key变为null对应的value,然而不是什么时候都满足,还是有一定可能性造成内存泄漏,应当适时使用remove()显式清理。


附:强引用,弱引用,软引用,虚引用

1、强引用
new创建一个对象,并赋值给一个变量,属于最常见的引用。此时JVM绝不会回收它,即使因为内存不足而终止程序。当生命周期结束,或者显式得将obj赋值为null,gc才会回收这部分内存。

Object obj = new Object();

2、软引用
java中软引用通过SoftReference类实现,内存不足的时候,gc会回收内存,否则不回收。可用于实现内存敏感的高速缓存。例如使用浏览器浏览网页,可以在内存中保存一部分内容,用于下一次的访问,不需要重复请求,如果内存不足时还可以直接回收,避免溢出。

SoftReference<Page> [] pages = new SoftReference<Page>[10];

3、弱引用
java中弱引用通过WeakReference类实现,不管内存是否充足,gc都会回收这部分内存,不过具体回收的时间不确定,取决于具体的回收策略。注意弱引用不会介入被引用对象的生命周期,也即不影响被引用对象的内存回收。
4、虚引用
虚引用通过PhantomReference类实现,对被引用对象没有任何影响。虚引用必须和引用队列联合使用,回收被引用对象时将虚引用加入关联的引用队列。程序通过判断引用队列是否加入了虚引用,来决定回收内存前采用必要的行动。
这里写图片描述
参考:http://zhangjunhd.blog.51cto.com/113473/53092/

0 0
原创粉丝点击