h5做的网站有哪些,上海企业在线,网络服务营销,wordpress 虚拟流量一:前言
一个问题引出的学习笔记 并发类库提供的线程池实现有哪些? 其实Executors已经为我们封装好了 4 种常见的功能线程池#xff0c;如下#xff1a;
定长线程池#xff08;FixedThreadPool#xff09;定时线程池#xff08;ScheduledThreadPool #xff09;可缓存…一:前言
一个问题引出的学习笔记 并发类库提供的线程池实现有哪些? 其实Executors已经为我们封装好了 4 种常见的功能线程池如下
定长线程池FixedThreadPool定时线程池ScheduledThreadPool 可缓存线程池CachedThreadPool单线程化线程池SingleThreadExecutor
那么接下来就复习一波线程和线程池
二:线程
1:关于线程的理解
自我理解:这是在javaweb中的文件上传部分 实际用到的线程 来帮助理解线程 一个线程就是一条执行路径 ,实际例子当中 我们请求一个页面如果需要很长的时间的话这时候我们需要设置线程来执行 请求消息中的代码,然后再写一个代码先显示出请求等待的信息官方解读: 线程程序执行流的最小执行单位是行程中的实际运作单位经常容易和进程这个概念混淆。那么线程和进程究竟有什么区别呢首先进程是一个动态的过程是一个活动的实体。简单来说一个应用程序的运行就可以被看做是一个进程而线程是运行中的实际的任务执行者。可以说进程中包含了多个可以同时运行的线程。
2:线程的声明周期
线程的生命周期线程的生命周期可以利用以下的图解来更好的理解:
3:单线程和多线程 三:线程池
1线程池从何处而来
在一个应用程序中我们需要多次使用线程也就意味着我们需要多次创建并销毁线程。而创建并销毁线程的过程势必会消耗内存。而在Java中内存资源是及其宝贵的所以我们就提出了线程池的概念 线程池Java中开辟出了一种管理线程的概念这个概念叫做线程池从概念以及应用场景中我们可以看出线程池的好处就是可以方便的管理线程也可以减少内存的消耗。
2:线程池的好处
(1) 降低资源消耗。 通过重复利用已创建的线程降低线程创建和销毁造成的消耗。(2) 提高响应速度。当任务到达时任务可以不需要等到线程创建就能立即执行。(3) 提高线程的可管理性。线程是稀缺资源如果无限制的创建不仅会消耗系统资源还会降低系统的稳定性使用线程池可以进行统一的分配调优和监控。
3:如何实现线程池
那么我们应该如何创建一个线程池那?Java中已经提供了创建线程池的一个类Executor类,而我们创建时一般使用它的子类ThreadPoolExecutor. 线程池的真正实现类是 ThreadPoolExecutor其构造方法有如下4种
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueueRunnable workQueue) {this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultThreadFactory(), defaultHandler);
}public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueueRunnable workQueue,ThreadFactory threadFactory) {this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,threadFactory, defaultHandler);
}public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueueRunnable workQueue,RejectedExecutionHandler handler) {this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultThreadFactory(), handler);
}public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueueRunnable workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {if (corePoolSize 0 ||maximumPoolSize 0 ||maximumPoolSize corePoolSize ||keepAliveTime 0)throw new IllegalArgumentException();if (workQueue null || threadFactory null || handler null)throw new NullPointerException();this.corePoolSize corePoolSize;this.maximumPoolSize maximumPoolSize;this.workQueue workQueue;this.keepAliveTime unit.toNanos(keepAliveTime);this.threadFactory threadFactory;this.handler handler;
}4:线程池的使用流程
// 创建线程池
ThreadPoolExecutor threadPool new ThreadPoolExecutor(CORE_POOL_SIZE,MAXIMUM_POOL_SIZE,KEEP_ALIVE,TimeUnit.SECONDS,sPoolWorkQueue,sThreadFactory);
// 向线程池提交任务
threadPool.execute(new Runnable() {Overridepublic void run() {... // 线程执行的任务}
});
// 关闭线程池
threadPool.shutdown(); // 设置线程池的状态为SHUTDOWN然后中断所有没有正在执行任务的线程
threadPool.shutdownNow(); // 设置线程池的状态为 STOP然后尝试停止所有的正在执行或暂停任务的线程并返回等待执行任务的列表5:线程池的工作原理 6:线程池的重要参数解读
(1):任务队列
(2):线程工厂threadFactory
线程工厂指定创建线程的方式需要实现 ThreadFactory 接口并实现 newThread(Runnable r) 方法。该参数可以不用指定Executors 框架已经为我们实现了一个默认的线程工厂
(3):拒绝策略handler 7:功能性线程池
嫌上面使用线程池的方法太麻烦其实Executors已经为我们封装好了 4 种常见的功能线程池如下
定长线程池FixedThreadPool定时线程池ScheduledThreadPool 可缓存线程池CachedThreadPool单线程化线程池SingleThreadExecutornewWorkStealingPool
1: newFixedThreadPool (固定数量的线程池)
创建的源码:
public static ExecutorService newFixedThreadPool(int nThreads) {return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueueRunnable());
}
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueueRunnable(),threadFactory);
}特点只有核心线程线程数量固定执行完立即回收任务队列为链表结构的有界队列。应用场景控制线程最大并发数。使用实例
// 1. 创建定长线程池对象 设置线程池线程数量固定为3
ExecutorService fixedThreadPool Executors.newFixedThreadPool(3);
// 2. 创建好Runnable类线程对象 需执行的任务
Runnable task new Runnable(){public void run() {System.out.println(执行任务啦);}
};
// 3. 向线程池提交任务
fixedThreadPool.execute(task);(2): newWorkStealingPool 这个线程池的特性从名字就可以看出 Stealing会窃取任务。 每个线程都有自己的双端队列当自己队列的任务处理完毕之后会去别的线程的任务队列尾部拿任务来执行加快任务的执行速率。 至于 ForkJoin 的话就是分而治之把大任务分解成一个个小任务然后分配执行之后再总和结果
(3): newSingleThreadExecutor (单线程池)
public static ExecutorService newSingleThreadExecutor() {return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueueRunnable()));
}
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueueRunnable(),threadFactory));
}特点只有 1 个核心线程无非核心线程执行完立即回收任务队列为链表结构的有界队列。 应用场景不适合并发但可能引起 IO 阻塞性及影响 UI 线程响应的操作如数据库操作、文件操作等。 使用实例:
public static ExecutorService newSingleThreadExecutor() {return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueueRunnable()));
}
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueueRunnable(),threadFactory));
}(4):newCachedThreadPool (可缓存的线程池)
创建方法的源码
public static ExecutorService newCachedThreadPool() {return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueueRunnable());
}
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueueRunnable(),threadFactory);
}特点无核心线程非核心线程数量无限执行完闲置 60s 后回收任务队列为不存储元素的阻塞队列。 应用场景执行大量、耗时少的任务。
所以它适合用在短时间内有大量短任务的场景。如果暂无可用线程那么来个任务就会新启一个线程去执行这个任务快速响应任务。 但是如果任务的时间很长那存在的线程就很多上下文切换就很频繁切换的消耗就很明显并且存在太多线程在内存中也有 OOM 的风险。 使用示例:
// 1. 创建可缓存线程池对象
ExecutorService cachedThreadPool Executors.newCachedThreadPool();
// 2. 创建好Runnable类线程对象 需执行的任务
Runnable task new Runnable(){public void run() {System.out.println(执行任务啦);}
};
// 3. 向线程池提交任务
cachedThreadPool.execute(task);5 newScheduledThreadPool定时线程池
创建方法的源码private static final long DEFAULT_KEEPALIVE_MILLIS 10L;public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {super(corePoolSize, Integer.MAX_VALUE,DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,new DelayedWorkQueue());
}public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory) {return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
}
public ScheduledThreadPoolExecutor(int corePoolSize,ThreadFactory threadFactory) {super(corePoolSize, Integer.MAX_VALUE,DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,new DelayedWorkQueue(), threadFactory);
}特点核心线程数量固定非核心线程数量无限执行完闲置 10ms 后回收任务队列为延时阻塞队列。 应用场景执行定时或周期性的任务。 使用示例:
/ 1. 创建 定时线程池对象 设置线程池线程数量固定为5
ScheduledExecutorService scheduledThreadPool Executors.newScheduledThreadPool(5);
// 2. 创建好Runnable类线程对象 需执行的任务
Runnable task new Runnable(){public void run() {System.out.println(执行任务啦);}
};
// 3. 向线程池提交任务
scheduledThreadPool.schedule(task, 1, TimeUnit.SECONDS); // 延迟1s后执行任务
scheduledThreadPool.scheduleAtFixedRate(task,10,1000,TimeUnit.MILLISECONDS);// 延迟10ms后、每隔1000ms执行任务参考自这篇博客