介绍
单个线程使用完随即被销毁,如果在list中频繁创建、销毁线程,会给服务器带来不小的性能开支,所有使用线程池将线程的创建、销毁工作统一处理,最后销毁,以此来提高效率 。
//普通创建线程方式一
new Thread(() -> {
dosomething();
}).start();
//方式二
((Runnable) () -> dosomething()).run();
一、几种常用的线程池
-
newSingleThreadExecutor
创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。ExecutorService service = Executors.newSingleThreadExecutor(); service .execute(() -> { try{ dosomething(); }catch(Exception e){ log.error(e); } });
-
newFixedThreadPool
创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。ExecutorService service = Executors.newFixedThreadPool(5); service.execute(() -> { try{ dosomething(); }catch(Exception e){ log.error(e); } });
-
newCachedThreadPool
创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,
那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。ExecutorService service = Executors.newCachedThreadPool(); service.execute(() -> { try{ dosomething(); }catch(Exception e){ log.error(e); } });
-
newScheduledThreadPool
创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求。ExecutorService service = Executors.newScheduledThreadPool(2); long initialDelay1 = 1; long period1 = 1; // 从现在开始1秒钟之后,每隔1秒钟执行一次job1 ((ScheduledExecutorService) service).scheduleAtFixedRate( new Thread(() -> { }), initialDelay1, period1, TimeUnit.SECONDS); long initialDelay2 = 1; long delay2 = 1; // 从现在开始2秒钟之后,每隔2秒钟执行一次job2 ((ScheduledExecutorService) service).scheduleWithFixedDelay( new Thread(() -> { }), initialDelay2, delay2, TimeUnit.SECONDS);
二、 @Async
该注解标注该方法或类是一个异步的方法
注意 该注解在同一类中使用不会生效
@EnableAsync //启动类注解
@SpringBootApplication
public class ManageApplication {
....
}
@Component //交给spring处理初始化该类
public class Jobs {
@Async
public void tes12() {
System.out.println("tes12");
}
}
@Component
public class JobTest{
@Autowired
Jobs dj;
public void excute() {
dj.tes12(); //异步执行
}
}
线程中出现异常 外部的try是捕获不到异常的(一个线程一个工作空间 互不干扰)
如:
try {
new Thread(() -> {
System.out.println(1 / 0);
}).start();
System.out.println("succ");
} catch (Exception e) {
System.out.println(e+"Thread"); //此条语句不会输出
}
解决方案
//1、实现 UncaughtExceptionHandler 重写uncaughtException方法
class MyUncaughtExceptionhandler implements Thread.UncaughtExceptionHandler {
/**
* 捕获异常 线程当中出现的异常 将在这里捕获
*/
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("caught " + e);
}
//2、在线程中try
new Thread(() -> {
try{
System.out.println(1 / 0);
} catch (Exception e) {
System.out.println(e+"Thread");
}
}).start();
submit =>有返回值future对象
execute => 无返回值
lock.lock();获得锁 如果线程拿到锁,将会一直等待
lock.unlock();释放锁
lock.trylock(5,TimeUnit.SECONDS);
尝试获得锁,如果获取不到将返回false 不会等待执行(可以设置时间) lock.unlock();释放锁