关于线程池、信号量等理解。

之前一直不理解ThreadLoca 这个对象的作用,也不知道为何会有内存泄露。前几天看到了一篇文章,讲解关于TheadLocal的知识,感觉挺好的,做下笔录。

package com.teligen.demo.service;


import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPoolTest {
static class LocalVariable {
private Long[] a = new Long[1024 * 1024];
}

final static ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(10, 20, 1, TimeUnit.MINUTES, new LinkedBlockingDeque<>());

final static ThreadLocal<LocalVariable> localVariable = new ThreadLocal<LocalVariable>();

public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 50; i++) {
poolExecutor.execute(new Runnable() {
@Override
public void run() {
//ThreadLocal 设置了本地线程变量,但ThreadLocal只是一个辅助类。核心还是ThreadLocalMap
localVariable.set(new LocalVariable());
System.out.println("use local varaible");
//这里需要remove 这个ThreadLocal对象。因为线程池始终会持有这个ThreadLocal对象引用,如果不调用remove,内存会一直不被释放
//这个时候,如果jvm 在进行gc的时候,发现内存不足,而key又为弱引用,则key会被gc回收。
//这种情况下,key已经为null,但是value又没有被置位null,则会导致value无法再被使用,也就是内存泄露
localVariable.remove();
}
});

Thread.sleep(1000);
}
System.out.println("pool execute over");

//定义5个容量的信号量
Semaphore semaphore = new Semaphore(5);
for (int i = 0; i < 20; i++) {
poolExecutor.execute(new Runnable() {
@Override
public void run() {
try {
//获取信号量
semaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程:" + Thread.currentThread() + "获得了信号量");
//释放信号量
semaphore.release();
}
});
}

}
}


-----------------------------------------------------------------------------------------------------------------
未完待续
原文地址:https://www.cnblogs.com/drafire/p/14362559.html