本文共 4070 字,大约阅读时间需要 13 分钟。
背景:2019年4月春招找实习,面试华为后端开发,面试官上来给了一张A4纸,让手写一个java线程池,要求可运行。
使用ExecutorService框架胡乱写了一点线程池的东西,但明显是不足以运行起来的。最后也以至于面试挂掉了。。秋招已经开始了,所以自己查看资料弄清楚了线程池的原理之后,编写了一个自己的线程池,记录一下。============================ 分割线 ================================
package scu.stone.thread;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.BlockingQueue;public class MyThreadPool { //线程池中默认线程的个数为5 private static int WORK_NUM = 5; //队列默认任务为100 private static int TASK_COUNT = 100; //工作线程数组 private WorkThread[] workThreads; //等待队列 private final BlockingQueuetaskQueue; //用户在构造这个线程池时,希望启动的线程数 private final int workerNum; /** * 内部类,工作线程类 */ private class WorkThread extends Thread{ @Override public void run() { Runnable runnable = null; try { while (! isInterrupted()) { //如果没有被标记中断,则从对阻塞队列中取出任务执行 runnable = taskQueue.take(); //take:阻塞接口的移除方法 if (runnable != null) { System.out.println("Thread ID:" + getId() + " ready exec:" + runnable.toString()); runnable.run(); } runnable = null; //help gc } } catch (Exception e) { // TODO: handle exception } } //线程停止工作 public void stopWork() { interrupt(); } } //构造方法:创建具有默认线程个数的线程池 public MyThreadPool() { this(WORK_NUM,TASK_COUNT); } //创建线程池,workNum为线程池中工作线程的个数 public MyThreadPool(int workerNum, int taskCount) { if (workerNum <= 0) { workerNum = WORK_NUM; } if (taskCount <= 0) { taskCount = TASK_COUNT; } this.workerNum = workerNum; taskQueue = new ArrayBlockingQueue<>(taskCount); workThreads = new WorkThread[workerNum]; for (int i = 0; i < workerNum; i++) { workThreads[i] = new WorkThread(); //new一个工作线程 workThreads[i].start(); //启动工作线程 } Runtime.getRuntime().availableProcessors(); } //执行任务,其实就是把任务加入任务队列,什么时候执行由线程池管理器决定 public void execute(Runnable task) { try { taskQueue.put(task); //put:阻塞接口的插入 } catch (Exception e) { // TODO: handle exception } } //销毁线程池,该方法保证所有任务都完成的情况下才销毁所有线程,否则等待任务完成再销毁 public void destory() { //工作线程停止工作,且置为null System.out.println("ready close thread..."); for (int i = 0; i < workerNum; i++) { workThreads[i].stopWork(); workThreads[i] = null; //help gc } taskQueue.clear(); //清空等待队列 } //覆盖toString方法,返回线程信息:工作线程个数和已完成任务个数 @Override public String toString() { return "WorkThread number:" + workerNum + " ==分割线== wait task number:" + taskQueue.size(); }}
2.任务类
package scu.stone.thread;import java.util.Random;public class MyTask implements Runnable { private String name; public String getName() { return name; } private Random random = new Random(); public MyTask(String name) { this.name = name; } @Override public void run() { try { Thread.sleep(random.nextInt(1000) + 2000); } catch (Exception e) { System.out.println(Thread.currentThread().getId() + "sleep InterruptedException:" + Thread.currentThread().isInterrupted()); } System.out.println("task--- " + name + "---done!"); }}
3.测试类
package scu.stone.thread;import java.util.concurrent.BlockingQueue;import java.util.concurrent.RejectedExecutionHandler;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;public class TestMyThreadPool extends ThreadPoolExecutor{ public TestMyThreadPool(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueueworkQueue,RejectedExecutionHandler handler) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler); } public static void main(String[] args) throws InterruptedException { //创建3个线程的线程池 MyThreadPool myThreadPool = new MyThreadPool(3, 3); myThreadPool.execute(new MyTask("A")); myThreadPool.execute(new MyTask("B")); myThreadPool.execute(new MyTask("C")); myThreadPool.execute(new MyTask("D")); myThreadPool.execute(new MyTask("E")); System.out.println(myThreadPool); Thread.sleep(10000); myThreadPool.destory(); //所有线程都执行完成后,再destory System.out.println(myThreadPool); }}
4.测试结果,如下:
转载地址:http://zvdgi.baihongyu.com/