线程池工作流程:
核心线程数(corePoolSize) :核心线程数的设计需要依据任务的处理时间和每秒产生的任务数量来确定,例如:执行一个任务需要0.1秒,系统百分之80的时间每秒都会产生100个任务,那么要想在1秒内处理完这100个任务,就需要10个线程,此时我们就可以设计核心线程数为10;当然实际情况不可能这么平均,所以我们一般按照8020原则设计即可,既按照百分之80的情况设计核心线程数,剩下的百分之20可以利用最大线程数处理。
任务队列长度(workQueue):任务队列长度一般设计为:核心线程数/单个任务执行时间*2即可(2表示最大等待时间为2秒);例如上面的场景中,核心线程数设计为10,单个任务执行时间为0.1秒,则队列长度可以设计为200。
最大线程数(maximumPoolSize):最大线程数的设计除了需要参照核心线程数的条件外,还需要参照系统每秒产生的最大任务数决定:例如:上述环境中,如果系统每秒最大产生的任务是1000个,那么,最大线程数=(最大任务数-任务队列长度)*单个任务执行时间;既: 最大线程数=(1000-200)*0.1=80个。
最大空闲时间(keepAliveTime) 这个参数的设计完全参考系统运行环境和硬件压力设定,没有固定的参考值,用户可以根据经验和系统产生任务的时间间隔合理设置一个值即可;
上面4个参数的设置只是一般的设计原则,并不是固定的,可以根据实际情况灵活调整!
自定义线程池:
/* 需求: 自定义线程池练习,这是任务类,需要实现Runnable; 包含任务编号,每一个任务执行时间设计为0.2秒 */ public class MyTask implements Runnable{ private int id; //由于run方法是重写接口中的方法,因此id这个属性初始化可以利用构造方法完成 public MyTask(int id) { this.id = id; } @Override public void run() { String name = Thread.currentThread().getName(); System.out.println("线程:"+name+" 即将执行任务:"+id); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程:"+name+" 完成了任务:"+id); } @Override public String toString() { return "MyTask{" + "id=" + id + '}'; } }
/* 需求: 编写一个线程类,需要继承Thread类,设计一个属性,用于保存线程的名字; 设计一个集合,用于保存所有的任务; */ public class MyWorker extends Thread{ private List<Runnable> tasks;
//利用构造方法,给成员变量赋值 public MyWorker(String name, List<Runnable> tasks) { super(name); this.tasks = tasks; } @Override public void run() { //判断集合中是否有任务,只要有,就一直执行任务 while (tasks.size()>0){ Runnable r = tasks.remove(0); r.run(); } } }
/* 这是自定义的线程池类; 成员变量: 1:任务队列 集合 需要控制线程安全问题 2:当前线程数量 3:核心线程数量 4:最大线程数量 5:任务队列的长度 成员方法 1:提交任务; 将任务添加到集合中,需要判断是否超出了任务总长度 2:执行任务; 判断当前线程的数量,决定创建核心线程还是非核心线程 */ public class MyThreadPool { // 1:任务队列 集合 需要控制线程安全问题 private List<Runnable> tasks = Collections.synchronizedList(new LinkedList<>()); //2:当前线程数量 private int num; //3:核心线程数量 private int corePoolSize; //4:最大线程数量 private int maxSize; //5:任务队列的长度 private int workSize; public MyThreadPool(int corePoolSize, int maxSize, int workSize) { this.corePoolSize = corePoolSize; this.maxSize = maxSize; this.workSize = workSize; } //1:提交任务; public void submit(Runnable r){ //判断当前集合中任务的数量,是否超出了最大任务数量 if(tasks.size() >= workSize){ System.out.println("任务:"+r+"被丢弃了..."); }else { tasks.add(r); //执行任务 execTask(r); } } //2:执行任务; private void execTask(Runnable r) { //判断当前线程池中的线程总数量,是否超出了核心数, if(num < corePoolSize){ new MyWorker("核心线程:"+num,tasks).start(); num++; }else if(num < maxSize){ new MyWorker("非核心线程:"+num,tasks).start(); num++; }else { System.out.println("任务:"+r+" 被缓存了..."); } } }
/* 测试类: 1: 创建线程池类对象; 2: 提交多个任务 */ public class MyTest { public static void main(String[] args) { //1:创建线程池类对象; MyThreadPool pool = new MyThreadPool(2,4,20); //2: 提交多个任务 for (int i = 0; i <30 ; i++) { //3:创建任务对象,并提交给线程池 MyTask my = new MyTask(i); pool.submit(my); } } }
Java内置线程池:
package com.fgy.demo07; public class RunnableImpl implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName() + "创建了一个新的线程"); } }
package com.fgy.demo07; public class ExtendsThread extends Thread { @Override public void run() { System.out.println(Thread.currentThread().getName() + "创建了一个新的线程"); } }
package com.fgy.demo07; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Demo01ThreadTool { public static void main(String[] args) { ExecutorService pool = Executors.newFixedThreadPool(3); // 创建线程池,初始化有三个线程 pool.submit(new RunnableImpl()); pool.submit(new Runnable(){ @Override public void run() { System.out.println(Thread.currentThread().getName() + "创建了一个新的线程"); } }); pool.submit(new Thread(){ @Override public void run() { System.out.println(getName() + "创建了一个新的线程"); } }); pool.submit(new ExtendsThread()); // pool-1-thread-2创建了一个新的线程 // Thread-0创建了一个新的线程 // pool-1-thread-3创建了一个新的线程 // pool-1-thread-1创建了一个新的线程 // 销毁线程池 pool.shutdown(); } }