java中的异步加载new Thread()方式
作者:TJkaklf
这篇文章主要介绍了java中的异步加载new Thread()方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
java的异步加载new Thread()
public class LoginInterface{ public String delSession(){ new Thread(new Runnable() { @Override public void run() { //需要执行的代码 } }).start(); }}
使用匿名内部类编译
class LoginInterface$1 implements Runnable { LoginInterface$1(LoginInterface paramLoginInterface, String paramString) { } public void run() { //要执行的代码 } }
聊聊new Thread()的危害
危害
1)开销大
每次new Thread() 都会创建新的对象,开销较大,无法复用增加垃圾回收的负担。
2)管理困难
每个new Thread() 都是独立的个体,无法有效的管控,无限制创建相互竞争,可能导致oom或者核心业务线程阻塞。
3)功能单一
无法定时执行,中断线程等功能。
线程池
1)复用已创建的线程,减少对象创建、消亡的开销,性能佳。
2)可控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。
3)可定时执行、中断线程等功能。
线程池大小
1)CPU密集型(计算型)
- 使用较小的线程池,一般是Cpu核心数+1
- 因为CPU密集型任务CPU的使用率很高,若开过多的线程,只能增加线程上下文的切换次数,带来额外的开销
2)IO密集型(查询访问型)
- 使用较大的线程池,一般CPU核心数 * 2
- 因为IO密集型CPU使用率不高,可以让CPU等待IO的时候处理别的任务,充分利用cpu时间
线程池创建【使用ThreadPoolExecutor手动创建】
public class CommonThreadPool { /** * 线程池对象 */ public static ExecutorService pool = null; /** * 线程池核心池的大小 */ private static final int CORE_POOL_SIZE = 5; /** * 获取当前系统的CPU 数目 */ private static int cpuNums = Runtime.getRuntime().availableProcessors(); /** * 线程池的最大线程数 */ private static final int MAX_POOL_SIZE = (cpuNums * 2) > CORE_POOL_SIZE ? (cpuNums * 2) : CORE_POOL_SIZE; static { pool = new ThreadPoolExecutor( CORE_POOL_SIZE, // 核心线程数 MAX_POOL_SIZE, // 最大线程数 通常核心线程数=最大线程数 当MAX_POOL_SIZE > CORE_POOL_SIZE 时,并不是当核心线程全部被占用后立马开始创建新的线程(只有在队列也满了之后才会开始新建线程) 0L, // 存活时间 >=0 0 永不回收【非核心线程除外】 TimeUnit.MILLISECONDS, // 单位 new ArrayBlockingQueue<Runnable>(100), // 队列 存放待执行任务 new ThreadFactoryBuilder().setNameFormat("CommonThread-%d").build(), // 创建工厂 new ThreadPoolExecutor.AbortPolicy()); // 拒绝策略 默认拒绝 丢弃 丢弃最老的 主线程执行 } }
禁用Executors创建线程池
1)Executors屏蔽的线程池的内部实现细节,开发人员需要根据服务器情况与业务场景定义更合适的线程池。
2)newFixedThreadPool 和 newSingleThreadExecutor的主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至 OOM。
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); } public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
3)newCachedThreadPool 和 newScheduledThreadPool:主要问题是线程数最大数是 Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至 OOM。
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); } public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue()); }
- LinkedBlockingQueue:队列默认大小Integer.MAX_VALUE,未指定大小时可以视为无界队列。
- SynchronousQueue:队列大容量为0,不存储任何数据。
- DelayedWorkQueue:无界,队列顺序按照延时时长排序。
任务执行流程
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。