当前位置 : 主页 > 编程语言 > java >

Java的ThreadLocal演示代码

来源:互联网 收集:自由互联 发布时间:2022-07-05
概念 概念​ 没用ThreadLocal出现线程安全问题 /** * 没用ThreadLocal 五个线程共享了 num变量 * 此时出现了线程安全问题 */ public class demo1 { private static int num = 0 ; /** * 结果下个线程的值是上一

概念

概念​

没用ThreadLocal出现线程安全问题

/**
* 没用ThreadLocal 五个线程共享了 num变量
* 此时出现了线程安全问题
*/
public class demo1 {

private static int num = 0;

/**
* 结果下个线程的值是上一个线程改变的值
* 因为 num 是线程共享的

*/
public static void main(String[] args) {
Thread[] threads = new Thread[5]; //定义五个线程
for (int i = 0; i < threads.length; i++) {

threads[i] = new Thread(() -> {
num += 5;
System.out.println(Thread.currentThread().getName() + ":" + num);
}, "thread-" + i);

}

for (Thread thread : threads) {
thread.start();

}

}
}

控制台输出

thread-0:5
thread-1:10
thread-3:20
thread-2:15
thread-4:25

用ThreadLocal解决上面的线程安全问题

/**
* 在demo1上做一个改良,使用ThreadLocal
* 通过 ThreadLocal 封装了一个 Integer 类型的 num 静态成员变量,并且初始值是0
* 每个线程相互独立了,同样是 static 变量,对于不同的线程而言,它没有被共享,
* 而是每个线程各一份,这样也就保证了线程安全。 也就是说,TheadLocal 为每一个线程提供了一个独立的副本!
* 搞清楚 ThreadLocal 的原理之后,有必要总结一下 ThreadLocal 的 API,其实很简单。
*/
public class demo2 {

// private static int num = 0;
static ThreadLocal<Integer> num = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return 0; //初始化0
}

};

/**
* 通过ThreadLocal去拿到值 然后修改完了再设置进去
* 结果:
* 每个线程获得都是副本
* @param args
*/
public static void main(String[] args) {
Thread[] threads = new Thread[5]; //定义五个线程
for (int i = 0; i < threads.length; i++) {

threads[i] = new Thread(() -> {
Integer localNum = num.get();//获取ThreadLocal中初始化的值
localNum = localNum + 5;
num.set(localNum); //设置修改以后的值
// num += 5;
System.out.println(Thread.currentThread().getName() + ":" + num.get());
}, "thread-" + i);

}

for (Thread thread : threads) {
thread.start();

}

}
}

控制台显示结果

thread-0:5
thread-3:5
thread-2:5
thread-1:5
thread-4:5

说明每个线程的变量都隔离了,这样解决了线程安全问题

ThreadLocal里面的泛型不能是static修饰的变量



上一篇:Java并发编程之Exchange概念和Demo *
下一篇:没有了
网友评论