多线程的使用
使用线程池ExecutorService
,exe.execute
来开始线程,thread,runabble,callabble
都可以,isTerminated
来判断线程池的线程是否都执行完毕
@Test
public void testThread() throws InterruptedException {
//创建线程池
ExecutorService exe = Executors.newFixedThreadPool(50);
for (int i = 1; i <= 1000; i++) {
//执行线程
exe.execute(new Runnable() {
@Override
public void run() {
System.out.println("1-->"+System.currentTimeMillis());
}
});
//执行线程
exe.execute(new Runnable() {
@Override
public void run() {
System.out.println("2-->"+System.currentTimeMillis());
}
});
//执行线程
exe.execute(new Runnable() {
@Override
public void run() {
System.out.println("3-->"+System.currentTimeMillis());
}
});
//执行线程
exe.execute(new Runnable() {
@Override
public void run() {
System.out.println("4-->"+System.currentTimeMillis());
}
});
}
while (true) {
//判断线程是否都执行完毕
if (exe.isTerminated()) {
System.out.println("结束了!");
break;
}
//睡眠一会再检查是否执行完毕
Thread.sleep(200);
}
//关闭线程池
exe.shutdown();
}
使用场景:生成报告,要填充数据、表格、图表,但是大数据量生成报告时间太久。
优化方案:使用多线程同时进行执行获取数据的sql和使用代码生成表格、生成图表、插入数据,然后判断线程都执行完毕后,再执行整合插入的方法,来缩短报告生成时间
ThreadLocal和InheritableThreadLocal
ThreadLocal
为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本,但是存在一个问题
,就是子线程获取该值的时候为Null
,可以用InheritableThreadLocal代替ThreadLocal
,依旧会为每个线程提供一个独立的副本,而不会共享
- ThreadLocal
@Test
public void test2() throws InterruptedException {
ThreadLocal num=new ThreadLocal();
num.set(100);
new Thread(()->{
System.out.println(num.get());
}).start();
Thread.sleep(1000);
System.out.println("完成");
}
可以看到子线程获取的值为空
2. InheritableThreadLocal
@Test
public void test2() throws InterruptedException {
//ThreadLocal变量无法传到子线程中使用,InheritableThreadLocal就是为了解决这个问题
InheritableThreadLocal num=new InheritableThreadLocal();
num.set(100);
new Thread(()->{
System.out.println("thread-before:"+num.get());
num.set(200);
System.out.println("thread-after:"+num.get());
}).start();
Thread.sleep(1000);
System.out.println("main:"+num.get());
System.out.println("完成");
}
正常取到值