编程问题二:写一个线程池
来源:互联网 发布:金融超市源码 编辑:程序博客网 时间:2024/06/05 07:12
对于大家来说,或多或少都知道Executor框架下的线程池。下面我介绍一下如何写一个线程池,因为这个问题的解决方法里有一个非常好的模型,相对来说这里的对象池的思想和生产者消费者关系模型也是非常重要的。
概念
在操作系统中,线程是操作系统调度的最小单元,同时线程也是一种受限的系统资源,即线程不能无限的生产,而且线程的创建和销毁都会有相对应的开销。
实现
在线程池中,我们的线程对象是可复用的。那么怎么复用呢?想明白这个就可以实现一个线程池了。对于这个问题,我们先按照:结构分析,结构概要图,详实实现来解决
结构分析
对于结构分析,主要是考虑可能涉及的对象、变量,功能。对于线程池的结构是比较容易猜测到的。
对象、变量:1.线程对象Thread(线程的对象池);2.被执行的Runnable集合;
功能:添加Runnable,执行任务,关闭任务
如果基于自己使用的ThreadPool来说,我们的结构可能不一样。主要是体现在功能上:添加Runable(execute(Runnable)),关闭任务shutdown()
在对象和功能进行分析后,他们两个点相互补充,譬如,关闭任务当然有一个变量来标记的,所以在对象上进行添加。
结构概要图
添加一点,在execute的时候,进行Notify任务队列。
详细实现
这就是代码了
package com.owant.java.study.thread.threadpool.div;import java.util.ArrayList;import java.util.Collections;import java.util.LinkedList;import java.util.List;import java.util.concurrent.atomic.AtomicLong;/** * Created by owant on 3/23/16. * <p/> * 1.存在的线程 * 2.管理存在线程的执行者 * <p> * <p> * 主要是复用对象Thread的对象池,每一个Thread对象是一个工作者 * 进行循环,如果没有任务进入await状态,在main线程进行execute的时候进行notify */public class DefaultThread<Job extends Runnable> implements ThreadPool<Job> { private static final int max_worker_numbers = 10; private static final int default_worker_numbers = 5; private static final int min_worker_numbers = 1; //循序表,记录加入的任务 private final LinkedList<Job> jobs = new LinkedList<>(); //工作者的列表 private final List<Worker> workers = Collections.synchronizedList(new ArrayList<Worker>()); private int workerNum = default_worker_numbers; //原子量,每一个线程都能操作,用于生产编号 private AtomicLong threadNum = new AtomicLong(); public DefaultThread() { initializeWorker(default_worker_numbers); } public DefaultThread(int num) { workerNum = num >= max_worker_numbers ? max_worker_numbers : (num <= min_worker_numbers ? min_worker_numbers : num); initializeWorker(workerNum); } /** * 创建线程池里的线程 * * @param num */ private void initializeWorker(int num) { for (int i = 0; i < num; i++) { Worker worker = new Worker(); //添加进入工作者集合 workers.add(worker); Thread thread = new Thread(worker, "ThreadPool-Worker-" + threadNum.incrementAndGet()); //工作者开始工作 thread.start(); } } @Override public void execute(Job run) { if (run != null) { synchronized (jobs) { jobs.addLast(run); jobs.notify(); } } } @Override public void shudown() { for (Worker w : workers) { w.shutdown(); } } @Override public void addWorkers(int num) { } @Override public void removedWorkers(int num) { } @Override public int getJobSize() { return 0; } private class Worker implements Runnable { private volatile boolean runflag = true; @Override public void run() { //一直在循环 while (runflag) { Job job = null; synchronized (jobs) { while (jobs.isEmpty()) { try { jobs.wait(); } catch (InterruptedException e) { e.printStackTrace(); Thread.currentThread().interrupt(); return; } } job = jobs.removeFirst(); } if (job != null) { job.run(); } } } public void shutdown() { runflag = false; } }}
阅读全文
1 0
- 编程问题二:写一个线程池
- 写一个线程池
- 写一个简单的线程池
- 写一个死锁线程
- 线程二-----------线程池的问题
- Windows核心编程-----线程池二
- Java并发编程(二)--线程池
- 一个线程池的例子(二)
- 探索并发编程(二)------写线程安全的Java代码
- 探索并发编程(二)------ 写线程安全的Java代码
- 探索并发编程(二)------写线程安全的Java代码
- 探索并发编程(二)------写线程安全的Java代码
- 探索并发编程(二)------写线程安全的Java代码
- 探索并发编程(二)------写线程安全的Java代码
- 写四个线程,二个加1,二个对一个变量减一
- 写四个线程,二个加1,二个对一个变量减一
- 编程野路:多线编程之二,一个线程类
- 用Java写一个多线程程序,如写四个线程,二个加1,二个对一变量减一,输出:
- spring中重要的数据结构
- VR帧传递流程
- Android下拉通知栏会影响Activity的生命周期方法吗?
- 经典算法详解--CART分类决策树、回归树和模型树
- 使用CSS实现两列布局
- 编程问题二:写一个线程池
- nodejs 主子进程通信
- Rails 导出 CSV
- mysql和oracle的函数对比
- hdu 1022 Train Problem I
- 矩阵快速幂模版
- Java8 Collection接口API翻译
- leetcode-39-Combination Sum
- 零基础写Java知乎爬虫之先拿百度首页练练手