线程池七大核心参数如下所示:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler )
1: 任务在提交的时候,首先判断核心线程数是否已满,如果没有满则直接添加到工作线程执行
2: 如果核心线程数满了,则判断阻塞队列是否已满,如果没有满,当前任务存入阻塞队列
3:如果阻塞队列也满了,则判断线程数是否小于最大线程数,如果满足条件,则使用临时线程执行任务如果核心或临时线程执行完成任务后会检查阻塞队列中是否有需要执行的线程,如果有,则使用非核心线程执行任务
4:如果所有线程都在忙着(核心线程+临时线程),则走拒绝策略
1.AbortPolicy:直接抛出异常,默认策略
2.CallerRunsPolicy:用调用者所在的线程来执行任务
3.DiscardOldestPolicy:丢弃阻塞队列中靠最前的任务,并执行当前任务
4.DiscardPolicy:直接丢弃任务
案例:
public class TestThreadPoolExecutor { static class MyTask implements Runnable { private final String name; private final long duration; public MyTask(String name) { this(name, 0); } public MyTask(String name, long duration) { this.name = name; this.duration = duration; } @Override public void run() { try { LoggerUtils.get("myThread").debug("running..." + this); Thread.sleep(duration); } catch (InterruptedException e) { e.printStackTrace(); } } @Override public String toString() { return "MyTask(" + name + ")"; } } public static void main(String[] args) throws InterruptedException { AtomicInteger c = new AtomicInteger(1); ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(2); ThreadPoolExecutor threadPool = new ThreadPoolExecutor( 2, 3, 0, TimeUnit.MILLISECONDS, queue, r -> new Thread(r, "myThread" + c.getAndIncrement()), new ThreadPoolExecutor.AbortPolicy()); showState(queue, threadPool); threadPool.submit(new MyTask("1", 3600000)); showState(queue, threadPool); threadPool.submit(new MyTask("2", 3600000)); showState(queue, threadPool); threadPool.submit(new MyTask("3")); showState(queue, threadPool); threadPool.submit(new MyTask("4")); showState(queue, threadPool); threadPool.submit(new MyTask("5",3600000)); showState(queue, threadPool); threadPool.submit(new MyTask("6")); showState(queue, threadPool); } private static void showState(ArrayBlockingQueue<Runnable> queue, ThreadPoolExecutor threadPool) { try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } List<Object> tasks = new ArrayList<>(); for (Runnable runnable : queue) { try { Field callable = FutureTask.class.getDeclaredField("callable"); callable.setAccessible(true); Object adapter = callable.get(runnable); Class<?> clazz = Class.forName("java.util.concurrent.Executors$RunnableAdapter"); Field task = clazz.getDeclaredField("task"); task.setAccessible(true); Object o = task.get(adapter); tasks.add(o); } catch (Exception e) { e.printStackTrace(); } } LoggerUtils.main.debug("pool size: {}, queue: {}", threadPool.getPoolSize(), tasks); }}
workQueue: 当没有空闲核心线程时,新来任务会加入到此队列排队,队列满会创建救急线程执行任务。
比较常见的有4个,用的最多是ArrayBlockingQueue和LinkedBlockingQueue。
inkedBlockingQueue** | ArrayBlockingQueue |
默认无界,支持有界 | 强制有界 |
底层是链表 | 底层是数组 |
是懒惰的,创建节点的时候添加数据 | 提前初始化 Node 数组 |
入队会生成新 Node | Node需要是提前创建好的 |
两把锁(头尾) | 一把锁 |
左边是LinkedBlockingQueue加锁的方式,右边是ArrayBlockingQueue加锁的方式
在java.util.concurrent.Executors类中提供了大量创建连接池的静态方法,常见就有四种
1.创建使用固定线程数的线程池
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>()); }
/** * @author springboot葵花宝典 * @description: TODO */public class FixedThreadPoolTest { static class FixedThreadDemo implements Runnable{ @Override public void run() { String name = Thread.currentThread().getName(); for (int i = 0; i < 2; i++) { System.out.println(name + ":" + i); } } } public static void main(String[] args) throws InterruptedException { //创建一个固定大小的线程池,核心线程数和最大线程数都是3 ExecutorService executorService = Executors.newFixedThreadPool(3); for (int i = 0; i < 5; i++) { executorService.submit(new FixedThreadDemo()); Thread.sleep(10); } executorService.shutdown(); }}
2.单线程化的线程池,它只会用唯一的工作线程来执行任 务,保证所有任务按照指定顺序(FIFO)执行
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>())); }
/** * @author springboot葵花宝典 * @description: TODO */public class NewSingleThreadTest { static int count = 0; static class Demo implements Runnable { @Override public void run() { count++; System.out.println(Thread.currentThread().getName() + ":" + count); } } public static void main(String[] args) throws InterruptedException { //单个线程池,核心线程数和最大线程数都是1 ExecutorService exec = Executors.newSingleThreadExecutor(); for (int i = 0; i < 10; i++) { exec.execute(new Demo()); Thread.sleep(5); } exec.shutdown(); }}
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, n ew SynchronousQueue<>()); }
/** * @author springboot葵花宝典 * @description: TODO */public class CachedThreadPoolTest { static class Demo implements Runnable { @Override public void run() { String name = Thread.currentThread().getName(); try { //修改睡眠时间,模拟线程执行需要花费的时间 Thread.sleep(100); System.out.println(name + "执行完了"); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) throws InterruptedException { //创建一个缓存的线程,没有核心线程数,最大线程数为Integer.MAX_VALUE ExecutorService exec = Executors.newCachedThreadPool(); for (int i = 0; i < 10; i++) { exec.execute(new Demo()); Thread.sleep(1); } exec.shutdown(); }}
public ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory, RejectedExecutionHandler handler{ super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue(), threadFactory, handler); }
/** * @author springboot葵花宝典 * @description: TODO */public class ScheduledThreadPoolTest { static class Task implements Runnable { @Override public void run() { try { String name = Thread.currentThread().getName(); System.out.println(name + ", 开始:" + new Date()); Thread.sleep(1000); System.out.println(name + ", 结束:" + new Date()); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) throws InterruptedException { //按照周期执行的线程池,核心线程数为2,最大线程数为Integer.MAX_VALUE ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(2); System.out.println("程序开始:" + new Date()); /** * schedule 提交任务到线程池中 * 第一个参数:提交的任务 * 第二个参数:任务执行的延迟时间 * 第三个参数:时间单位 */ scheduledThreadPool.schedule(new Task(), 0, TimeUnit.SECONDS); scheduledThreadPool.schedule(new Task(), 1, TimeUnit.SECONDS); scheduledThreadPool.schedule(new Task(), 5, TimeUnit.SECONDS); Thread.sleep(5000); // 关闭线程池 scheduledThreadPool.shutdown(); }}
候选人:
在线程池中一共有7个核心参数:
在拒绝策略中又有4中拒绝策略
候选人:
首先判断线程池里的核心线程是否都在执行任务,如果不是则创建一个新的工作线程来执行任务。如果核心线程都在执行任务,则线程池判断工作队列是否已满,如果工作队列没有满,则将新提交的任务存储在这个工作队 列里。如果工作队列满了,则判断线程池里的线程是否都处于工作状态,如果没有,则创建一个新的工作线程来执行任 务。如果已经满了,则交给拒绝策略来处理这个任务。
候选人:
在jdk中默认提供了4中方式创建线程池
本文链接:http://www.28at.com/showinfo-26-35298-0.html说一下线程池的核心参数,线程池的执行原理
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com
上一篇: 比亚迪面试,全程八股!
下一篇: 线程包括哪些状态,状态之间是如何变化?