博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
面试之Java线程池--手写自己的线程池
阅读量:4282 次
发布时间:2019-05-27

本文共 4070 字,大约阅读时间需要 13 分钟。

背景:2019年4月春招找实习,面试华为后端开发,面试官上来给了一张A4纸,让手写一个java线程池,要求可运行。

使用ExecutorService框架胡乱写了一点线程池的东西,但明显是不足以运行起来的。最后也以至于面试挂掉了。。秋招已经开始了,所以自己查看资料弄清楚了线程池的原理之后,编写了一个自己的线程池,记录一下。

============================ 分割线 ================================

一、首先回顾一下线程池的原理

线程池处理一个任务分三个阶段,具体如下图:

在这里插入图片描述

根据以上流程图,编写线程池代码

1.线程池类
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 BlockingQueue
taskQueue; //用户在构造这个线程池时,希望启动的线程数 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, BlockingQueue
workQueue,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/

你可能感兴趣的文章
shell脚本学习---nohup
查看>>
system系统调用的使用
查看>>
linux -- 进程的查看、进程id的获取、进程的杀死
查看>>
android暂停或停止其他音乐播放器的播放
查看>>
安卓系统定制常见问题解决
查看>>
Android系统默认值的设置
查看>>
音频和视频播放
查看>>
Android常用固件修改
查看>>
AudioFlinger,AudioPolicyService and Audio track分析
查看>>
Android 5.x 权限问题解决方法
查看>>
linux重定向及nohup不输出的方法
查看>>
Android 在 SElinux下 如何获得对一个内核节点的访问权限
查看>>
Android6.0 selinux没有对某个文件的权限(又neverAllow)处理方法
查看>>
Android如何判断当前手机是否正在播放音乐,并获取到正在播放的音乐的信息
查看>>
Android 6.0 新功能及主要 API 变更
查看>>
linux获取时间函数及计算时间差
查看>>
Android中的Audio播放:控制Audio输出通道切换
查看>>
Android中的Audio播放:竞争Audio之Audio Focus的应用
查看>>
Android之PowerManager电源管理
查看>>
Android6.0.1音乐apk获得audioFocus的流程
查看>>