前言

并发(Concurrency)一直谈论java绕不开的一个话题,从移动开发工程师到后端工程师,几乎所有的面试都要涉及到并发/多线程的一些问题。虽然多数时候我们使用线程池,都是已经实现好的框架——jdk7中就有现成的ThreadPoolExecutor供我们使用,不过,自己实现一个简化的线程池,对于帮助我们理解其内部原理还是有一些帮助的。

设计

核心思想如下:

  • 线程池实例为单例
  • 线程池实例中保存着一个线程数组,用来分发任务
  • 线程池中通过一个BlockingQueue实例,来实现FIFO的任务队列,这个实例同时被线程数组中的每一个线程拥有
  • 线程通过while循环,不断从队列中取出任务执行(Runnable

实现

首先是线程池示例SimpleThreadPool.java,使用单例模式。

public class SimpleThreadPool {
private static SimpleThreadPool ourInstance;
private static final int QUEUE_SIZE = 100; // todo 调整 最优的capacity
private PoolThread[] threadArray;
private BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<>(QUEUE_SIZE);
private boolean isStopped; public static SimpleThreadPool getInstance() {
if (ourInstance == null) {
ourInstance = new SimpleThreadPool();
}
return ourInstance;
} public SimpleThreadPool initPoolSize(int size) {
if (size < 1 || size > 10) {
throw new RuntimeException("size must be 1~10!");
}
threadArray = new PoolThread[size];
for (int i = 0; i < size; i++) {
threadArray[i] = new PoolThread(blockingQueue);
threadArray[i].start();
}
return this;
} public synchronized SimpleThreadPool execute(Runnable runnable) {
if (isStopped) {
throw new IllegalStateException("Thread Pool is stopped!");
}
blockingQueue.offer(runnable);
return this;
} public synchronized void doStop() {
for (PoolThread pt : threadArray) {
pt.doStop();
}
isStopped = true;
} }

然后是自定义的线程池线程,PoolThread.java

是否需要在run、doStop两个方法前声明synchronized,存疑。

public class PoolThread extends Thread {
private BlockingQueue<Runnable> blockingQueue;
private boolean isStopped; public PoolThread(BlockingQueue<Runnable> blockingQueue) {
this.blockingQueue = blockingQueue;
} @Override
public void run() {
while (!isStopped) {
try {
Runnable runnable = blockingQueue.take();
System.out.println(getName() + " is running...");
runnable.run();
} catch (InterruptedException e) {
// todo: log it
} catch (Exception e) {
throw new RuntimeException(e);
}
}
} public void doStop() {
interrupt();
isStopped = true;
}
}

写个Main函数测试一下。

public class Main {
public static void main(String[] args) {
SimpleThreadPool.getInstance().initPoolSize(10).execute(new Runnable() {
@Override
public void run() {
System.out.println("1+1=" + (1 + 1));
}
}).execute(new Runnable() {
@Override
public void run() {
System.out.println("2+2=" + (2 + 2));
}
}).execute(new Runnable() {
@Override
public void run() {
System.out.println("3+3=" + (3 + 3));
}
}).execute(new Runnable() {
@Override
public void run() {
System.out.println("4+4=" + (4 + 4));
}
}).execute(new Runnable() {
@Override
public void run() {
System.out.println("5+5=" + (5 + 5));
}
})
;
SimpleThreadPool.getInstance().doStop();
}
}

示例输出:

Thread-9 is running...
1+1=2
Thread-9 is running...
2+2=4
Thread-9 is running...
3+3=6
Thread-3 is running...
4+4=8
Thread-4 is running...
5+5=10

SimpleThreadPool实践的更多相关文章

  1. Quartz应用实践入门案例一(基于Web环境)

    Quartz是一个完全由java编写的开源作业调度框架,正是因为这个框架整合了许多额外的功能,所以在使用上就显得相当容易.只是需要简单的配置一下就能轻松的使用任务调度了.在Quartz中,真正执行的j ...

  2. spring-boot-2.0.3之quartz集成,最佳实践

    前言 开心一刻 快过年了,大街上,爷爷在给孙子示范摔炮怎么放,嘴里还不停念叨:要像这样,用劲甩才能响.示范了一个,两个,三个... 孙子终于忍不住了,抱着爷爷的腿哭起来:爷呀,你给我剩个吧! 新的一年 ...

  3. spring-boot-starter-quartz集群实践

    [**前情提要**]由于项目需要,需要一个定时任务集群,故此有了这个spring-boot-starter-quartz集群的实践.springboot的版本为:2.1.6.RELEASE:quart ...

  4. webp图片实践之路

    最近,我们在项目中实践了webp图片,并且抽离出了工具模块,整合到了项目的基础模板中.传闻IOS10也将要支持webp,那么使用webp带来的性能提升将更加明显.估计在不久的将来,webp会成为标配. ...

  5. Hangfire项目实践分享

    Hangfire项目实践分享 目录 Hangfire项目实践分享 目录 什么是Hangfire Hangfire基础 基于队列的任务处理(Fire-and-forget jobs) 延迟任务执行(De ...

  6. TDD在Unity3D游戏项目开发中的实践

    0x00 前言 关于TDD测试驱动开发的文章已经有很多了,但是在游戏开发尤其是使用Unity3D开发游戏时,却听不到特别多关于TDD的声音.那么本文就来简单聊一聊TDD如何在U3D项目中使用以及如何使 ...

  7. Logstash实践: 分布式系统的日志监控

    文/赵杰 2015.11.04 1. 前言 服务端日志你有多重视? 我们没有日志 有日志,但基本不去控制需要输出的内容 经常微调日志,只输出我们想看和有用的 经常监控日志,一方面帮助日志微调,一方面及 ...

  8. 【大型网站技术实践】初级篇:借助Nginx搭建反向代理服务器

    一.反向代理:Web服务器的“经纪人” 1.1 反向代理初印象 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从 ...

  9. Windows平台分布式架构实践 - 负载均衡

    概述 最近.NET的世界开始闹腾了,微软官方终于加入到了对.NET跨平台的支持,并且在不久的将来,我们在VS里面写的代码可能就可以通过Mono直接在Linux和Mac上运行.那么大家(开发者和企业)为 ...

随机推荐

  1. javascript实现图片切换、自动走、鼠标移入会停止,移出继续走

    要实现以上效果并不难,把功能分开一步一步来实现就变得简单了,录制动态图不流畅,看代码意会吧! <!doctype html> <html lang="en"> ...

  2. 1.4 云计算的SPI服务模型

    云计算是通过共享资源池的方式来提高资源利用率的.在云计算中,根据其资源池中资源的类别,可以把云计算的服务模型分为三种,即所谓的SPI 模型   应用程序 Software as a Service ( ...

  3. nodejs--模块

    在客户端可以将所有的javascript代码分割成几个JS文件,然后在浏览器中将这些JS文件合并.但是在nodejs中是通过以模块为单位来划分所有功能的.每一个模块为一个JS文件,每一个模块中定义的全 ...

  4. 11.14 T2 小x的旅行(小x的旅行)

    1.小x的旅行   (travel.pas/c/cpp) [问题描述] 小x大学毕业后,进入了某个公司做了高层管理,他每年的任务就是检查这个公司在全国各地N个分公司的各种状况,每个公司都要检查一遍,且 ...

  5. JAVA的单例模式与延时加载

    延迟加载(lazy load)是(也称为懒加载),也叫延迟实例化,延迟初始化等,主要表达的思想就是:把对象的创建延迟到使用的时候创建,而不是对象实例化的时候创建.延迟加载机制是为了避免一些无谓的性能开 ...

  6. Kali Linux 2.0配置并安装常用的工具

    Kali Linux 前身是著名渗透测试系统BackTrack ,是一个基于 Debian 的 Linux 发行版,包含很多安全和取证方面的相关工具. Kali Linux 2.0是基于Debian ...

  7. canvas 动态画线

    <!--实现鼠标按下的时候,移动进行绘制,鼠标抬起结束绘图,用到的事件有mousedown mousemove mouseup用的的canvas api 有 beginPath moveTo l ...

  8. textarea光标处插入文字

    (function($) { $.fn.extend({ //myField 对象元素 myValue 插入值 insertAtCursor: function(myField,myValue) { ...

  9. Smart_Script

    target_type Name Value target_param1 target_param2 target_param3 target_x target_y target_z target_o ...

  10. 用帝国CMS时遇到的问题

    今天用帝国CMS时出现了如下提示: Table 'tuanwei.phome_ecms_twnews_index' doesn't exist delete from ***_ecms_t 删除栏目时 ...