package com.test001.threadpool;

import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Vector;
import java.util.concurrent.Callable;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong; public class ThreadPool <T>{
private int maxRunThreadNum;
private int maxWaitTaskNum;
private int minActiveThreadNum;
private int addTaskTimeout;
private Vector<Worker> workerList;
private static ThreadPool threadPool;
private LinkedBlockingQueue<Task<T>> taskBlockingDeque;
private AtomicLong workingNum = new AtomicLong();
//初始化参数
private ThreadPool(){
maxRunThreadNum = 10;
maxWaitTaskNum = 50;
minActiveThreadNum = 5;
addTaskTimeout = 5;
workerList = new Vector<>(maxRunThreadNum);
taskBlockingDeque = new LinkedBlockingQueue<>(maxWaitTaskNum);
createWorker(minActiveThreadNum); } public synchronized static <T> ThreadPool<T> getThreadPool(){
if(threadPool==null){
threadPool = new ThreadPool<T>();
}
return threadPool;
} public synchronized void close(){
for (Worker worker:workerList){
worker.close();
worker.interrupt();
}
}
// 添加线程
private synchronized boolean createWorker(int num){
if(workerList.size()+num<maxRunThreadNum){
for (int i=0;i<num;i++) {
Worker worker = new Worker();
workerList.add(worker);
worker.start();
}
return true;
}
return false;
} public Future<T> addTask(Callable<T> callable) throws Exception {
// TODO::考虑 计算当前启动的worker和最大worker之间的数量 以及当前正在运行的和启动的数量,启动更多worker
System.out.println("add");
Task<T> task = new Task<>(callable);
boolean flag = taskBlockingDeque.offer(task,addTaskTimeout, TimeUnit.SECONDS);
if(!flag) return null;
return task.getFuture();
} class Task<T>{
public Callable<T> getCallable() {
return callable;
} public void setCallable(Callable<T> callable) {
this.callable = callable;
} public Future<T> getFuture() {
return future;
} public void setFuture(Future<T> future) {
this.future = future;
} private Callable<T> callable;
private Future<T> future; public Task(Callable<T> callable){
this.callable = callable;
this.future = new Future<>();
} } class Worker extends Thread{
private boolean closeFlag = false;
@Override
public void run() {
while(!closeFlag){
if(taskBlockingDeque.isEmpty()){
// TODO::新增信号量,等待唤醒
}else{
Task<T> task = taskBlockingDeque.poll();
if(task!=null){
Callable<T> callable = task.getCallable();
Future<T> future = task.getFuture();
try {
workingNum.getAndDecrement();
T t = callable.call();
// System.out.println("get t="+t);
future.set(t);
workingNum.decrementAndGet();
} catch (Exception e) {
e.printStackTrace();
}
} }
}
} public void close(){
closeFlag = true;
}
} public static void main(String[] args) throws Exception {
long startTime = System.currentTimeMillis(); //获取开始时间 ThreadPool<Integer> t = ThreadPool.getThreadPool();
List<Future<Integer>> futures = new LinkedList<>();
for (int i=1;i<=50;i++){
Integer data = i;
Future<Integer> f = t.addTask(()->{
Random rd = new Random();
// int num = rd.nextInt(5)+1;
int num = data;
// System.out.println("start\tdata="+data+"\t thread="+Thread.currentThread().getName()+"\tsleep:"+num);
Thread.sleep(num*1000);
System.out.println("end\tdata="+data+"\tthread="+Thread.currentThread().getName());
return num;
});
futures.add(f);
}
// Thread.sleep(25*1000);
int i =0;
for(Future<Integer> f :futures){
i++;
System.out.println("get data\t"+i+"="+f.get());
}
t.close();
long endTime = System.currentTimeMillis(); //获取结束时间
System.out.println("程序运行时间:" + (endTime - startTime) + "ms"); //输出程序运行时间
} } class Future<T>{
private volatile boolean hasResp = false;
private T t;
private Semaphore semaphore = new Semaphore(1);
public Future(){
try {
semaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
} public T get() throws InterruptedException {
// 等待对应的信号量,然后到对应任务编号,取出对应的值
semaphore.acquire();
return t;
} protected void set(T t){
this.t = t;
semaphore.release();
} }

java手写线程池,完善中的更多相关文章

  1. 手写线程池,对照学习ThreadPoolExecutor线程池实现原理!

    作者:小傅哥 博客:https://bugstack.cn Github:https://github.com/fuzhengwei/CodeGuide/wiki 沉淀.分享.成长,让自己和他人都能有 ...

  2. Java实现终止线程池中正在运行的定时任务

    源于开发 最近项目中遇到了一个新的需求,就是实现一个可以动态添加定时任务的功能.说到这里,有人可能会说简单啊,使用quartz就好了,简单粗暴.然而quartz框架太重了,小项目根本不好操作啊.当然, ...

  3. Go组件学习——手写连接池并没有那么简单

    1.背景 前段时间在看gorm,发现gorm是复用database/sql的连接池. 于是翻了下database/sql的数据库连接池的代码实现,看完代码,好像也不是很复杂,但是总觉得理解不够深刻,于 ...

  4. Java多线程和线程池

    转自:http://blog.csdn.net/u013142781/article/details/51387749 1.为什么要使用线程池 在Java中,如果每个请求到达就创建一个新线程,开销是相 ...

  5. Java实现的 线程池

    由于最近开始学习java,用到了线程池,按照之前c++的写法写出此java版的线程池 TaskRunnale实现相关任务的接口,具体要实现什么任务在相应的run函数中实现. package threa ...

  6. java并发包&线程池原理分析&锁的深度化

          java并发包&线程池原理分析&锁的深度化 并发包 同步容器类 Vector与ArrayList区别 1.ArrayList是最常用的List实现类,内部是通过数组实现的, ...

  7. 线程池是什么?Java四种线程池的使用介绍

    使用线程池的好处有很多,比如节省系统资源的开销,节省创建和销毁线程的时间等,当我们需要处理的任务较多时,就可以使用线程池,可能还有很多用户不知道Java线程池如何使用?下面小编给大家分享Java四种线 ...

  8. Java 多线程:线程池

    Java 多线程:线程池 作者:Grey 原文地址: 博客园:Java 多线程:线程池 CSDN:Java 多线程:线程池 工作原理 线程池内部是通过队列结合线程实现的,当我们利用线程池执行任务时: ...

  9. 自己动手写线程池——向JDK线程池进发

    自己动手写线程池--向JDK线程池进发 前言 在前面的文章自己动手写乞丐版线程池中,我们写了一个非常简单的线程池实现,这个只是一个非常简单的实现,在本篇文章当中我们将要实现一个和JDK内部实现的线程池 ...

随机推荐

  1. Linker errors in Android NDK (undefined reference to `__cxa_end_cleanup')

    在 Android 中移植一个库(该库 使用了 libstlport )时 产生如下错误: ./obj/local/armeabi/objs/jniWrapper/native.o: In funct ...

  2. 【原创】大数据基础之Zookeeper(3)选举算法

    提到zookeeper选举算法,就不得不提Paxos算法,因为zookeeper选举算法是Paxos算法的一个变种: Paxos要解决的问题是:在一个分布式网络环境中有众多的参与者,但是每个参与者都不 ...

  3. Java_运算符

    目录 一.算术运算符 二.关系运算符 三.位运算符 四.赋值运算符 五.条件运算符 六.instanceof 运算符 七.逻辑运算符 一.算术运算符 加 减 乘 除 取余 自增 自减(+ - * / ...

  4. 集腋成裘-08-ECharts -简介-01

    目标:让数据说话. 大数据时代的到来以及有效应用,大幅度提升了企业的管理能力.决策科学化与可执行性水平,推动传统决策方式朝着数据驱动转型.可视化数据分析对决策者产生的意义将在事前预测.事中感知以及事后 ...

  5. docker 部署mvc项目 <四>

    一:部署方式 直接使用centos镜像,做一个镜像,此镜像制定端口号,在centos容器中安装jexus独立版,就可以了 docker run -d -p : -itd --name wds cent ...

  6. Redis 数据结构之dict(2)

    本文及后续文章,Redis版本均是v3.2.8 上篇文章<Redis 数据结构之dict>,我们对dict的结构有了大致的印象.此篇文章对dict是如何维护数据结构的做个详细的理解. 老规 ...

  7. Spring Data REST PATCH请求 远程代码执行漏洞案例(CVE-2017-8046)

    恶意的PATCH请求使用精心构造的JSON数据提交到spring-data-rest服务可以执行任意JAVA代码 1. 背景 Spring Data REST是Spring Data项目的一部分,可以 ...

  8. vue-cli按需加载,懒加载组件

    vue来做一个单页面应用,当我们的项目越来越大,组件越来越多的时候,首次启动项目户特别慢,就算做一个加载框,蒙层之类的,体验也不会好,这个时候就需要按需加载 1.什么叫按需加载 所谓按需加载,顾名思义 ...

  9. nodejs入门篇之linux版的nodejs简易环境安装部署

    第一步:下载二进制安装包 根据linux的不同版本选择32位或64位,因为我的linux的虚拟机是64位的,所以我选择的是64位二进制安装文件(Linux Binariesx64),可以右键选择在新窗 ...

  10. 使用Python下载文件

    python -c "with open('/tmp/file.sh', 'wb') as f: import urllib2; f.write(urllib2.urlopen('http: ...