今天由于老大让我向数据库中添加百万条数据用来做测试,考虑到单线程插入数据可能要花很久的时间,于是想到了用线程池来进行插入操作,但是里面有个一个唯一性约束字段,然后在这个过程中遇到了好几个问题:
- 一开始使用线程池的时候由于唯一性约束字段的存在,需要将一个公有变量变成私有变量(每个线程在执行过程中变量需要不被外界修改),但是线程池中的线程是通过实现Runnable接口方式创建的,那么类中的私有变量其实是公有变量。
- 了解到ThreadLocal的用法后,也踩了几次坑,这里总结一些ThreadLocal的用法:尽量使用
private static
声明ThreadLocal变量;出main线程外,只有在run()中才能调用到TheadLocal变量(run中调用的其他方法中也能调用到,一开始将其放在在MyThread类的构造方法中,一直有NPE报出),说明只有在run()中,这个线程才算真正有了自己的生命周期。 - 线程数和循环次数不要太狠,尤其是在添加了对象到List中的时候,很容易出现内存不足异常。
- ThreadLocal变量在不需要当前存放的值的时候,必须使用remove方法清除,这点也是一个大坑,下面主要是介绍这个坑以及解决方法。
- 调用线程池的shutdown()方法意味着该线程池在线程池中的所有线程执行完毕后就“关机了”,将不再接受任何调用。
(1)在线程中执行添加一段连续的Integer到List中;
(2)(1)中的Integer不能是重复的;
(3)在main中向线程池中添加10条线程,并启动它们;
(4)线程池中的每条线程循环执行10次;
未使用remove()的代码(其实也就是我注释了remove)如下:
public class ThreadLocalTest {
static Integer initNum = 1; //初始数据
static int step = 10; //步长
static int threads = 10; //线程数
private static ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
public static