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. Set集合(scala)

    特点 Set集合最大的特点是:无序 不可重复 定长Set集合 无序 scala> val set = Set(1,5,4,3,7) set: scala.collection.immutable ...

  2. github密钥

    官网英文资料:https://help.github.com/articles/connecting-to-github-with-ssh/ 1.生成SSH keys文件id_rsa.pub ssh- ...

  3. tcpdump抓包常用命令列举

    情形一.采集指定网络接口和端口的数据包 sudo tcpdump -s 0 -x -n -tttt -i bond0  port  55944 -w /tmp/mysql_tmp.tcp 情形二.采集 ...

  4. 著名的3像素Bug(div+img,多出几像素)

    <div><img src="...."></div> 给img的css设置display: block;/*用来去除div下边莫名多出来的3p ...

  5. __libc_csu_init函数的通用gadget

    . ; =============== S U B R O U T I N E ======================================= . . . public __libc_ ...

  6. “System.FormatException”类型的未经处理的异常在 System.IdentityModel.dll 中发生 其他信息: 十六进制字符串格式无效。

    如果你的 WebService 客户端证书配置都没问题,唯独调用接口会出现这个错误 “System.FormatException”类型的未经处理的异常在 System.IdentityModel.d ...

  7. Vue H5 项目模板

    使用了 mint-ui sass vue fastclick vue router 一个项目的初始化状态,一个新项目,陆陆续续花了2天时间搭起来的. 里面有mint-ui的基本用法 tabbar 还有 ...

  8. C# 默认访问修饰符

    c# 中类,成员,枚举,结构等默认访问修饰符是? 根据MSDN文档有: [MSDN] Classes and structs that are not nested within other clas ...

  9. (三)ajax请求不同源之服务器代理跨域

    一.基本原理 Server Proxy,顾名思义,在服务器端设置一个代理,由服务器端向跨域的网站发出请求,再将请求结果返回给前端,成功避免同源策略的限制. 二.客户端和服务端代码 1.在localho ...

  10. WPF:解决数据绑定时不更新数据的问题

    当用户在窗体控件中修改数据时,如果此时用户点击其它窗体会出现数据没有更新的情况. 这是由于数据绑定默认是通过失去焦点来提交数据的.可通过属性变更方法来更新数据: <TextBox.Text> ...