手写精简版的java线程池
一、谈谈池化技术
- 简单点来说,就是预先保存好大量的资源,这些是可复用的资源,你需要的时候给你。对于线程,内存,oracle的连接对象等等,这些都是资源,程序中当你创建一个线程或者在堆上申请一块内存时,都涉及到很多系统调用,也是非常消耗CPU的,如果你的程序需要很多类似的工作线程或者需要频繁的申请释放小块内存,如果没有在这方面进行优化,那很有可能这部分代码将会成为影响你整个程序性能的瓶颈。池化技术主要有线程池,内存池,连接池,对象池等等,对象池就是提前创建很多对象,将用过的对象保存起来,等下一次需要这种对象的时候,再拿出来重复使用。
二、再来看看我们今天所要关注的线程池
-
线程池的作用:为了限制系统中执行线程的数量。
- 根据系统的自身配置、环境等情况,可以自动或手动设置线程数量,达到运行的最佳效果;少了浪费了系统资源,多了造成系统拥挤效率不高。用线程池控制线程数量,其他线程排队等候。一个任务执行完毕,再从队列的中取最前面的任务开始执行。若队列中没有等待进程,线程池里的线程处于等待。当一个新任务需要运行时,如果线程池中有等待的工作线程(空闲的线程),就可以开始运行了;否则依旧在等待队列。
-
为什么要使用线程池
-
线程的创建/销毁伴随着系统开销,若是过于频繁的创建/销毁线程,会很大程度上影响处理效率;如果使用线程池就能达到每个工作线程都可以被重复利用,可执行多个任务。
- 可以根据自身系统的承受能力,调整线程池中线程的数目,防止因为消耗过多的内存。
- 对线程进行一些简单的管理;如定时开始,周期执行,并发数控制等等。
三、下面代码实现精简版的线程池
- 创建一个线程池接口第一一些基本的方法(模仿jdk里面写个线程池接口)ThreadPoolInterface.java
package com.zzq.core.pool;
/**
* zhouzhongqing
* 2018年5月6日13:53:35
* 接口
* */
public interface ThreadPoolInterface {
/**
* @param task
* @return
* 添加任务
*/
int addWork(Runnable task);
/**
* 停止全部线程执行任务
* @return int
*
*/
int stopAll();
}
- 实现类ThreadPoolInterfaceImpl.java
package com.zzq.core.pool;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadPoolInterfaceImpl implements ThreadPoolInterface {
//线程的个数 默认开启100个线程执行任务
private static volatile Integer workNum = 100;
//任务队列
private static LinkedBlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<>();
static AtomicInteger count = new AtomicInteger(0);
WorkThread [] workThread;
public ThreadPoolInterfaceImpl() {
this(workNum);
}
public ThreadPoolInterfaceImpl(int workNum) {
if(0 != workNum) ThreadPoolInterfaceImpl.workNum= workNum;
workThread = new WorkThread[workNum];
//预先开启线程
for (int i = 0; i < workNum; i++) {
workThread[i] = new WorkThread();
Thread t = new Thread(workThread[i],"线程 - "+ i + ": name");
t.start();
System.out.println("线程: "+ i + ":已开启");
}
}
public int addWork(Runnable task) {
taskQueue.offer(task);
taskQueue.notifyAll();
return 1;
}
@Override
public int stopAll() {
//new WorkThread().setIsRuning();
if(null != workThread){
for(int i = 0;i <workThread.length ; i++){
workThread[i].setIsRuning();
}
return 1;
}
return 0;
}
public static void main(String[] args) {
new ThreadPoolInterfaceImpl();
}
static class WorkThread extends Thread{
volatile boolean isRuning = true;
@Override
public void run() {
//预先开好的线程去消费这个任务队列
while (true) {
if(isRuning){
if(isRuning && taskQueue.isEmpty()){
try {
taskQueue.wait(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("等待添加任务状态");
}else{
if(!taskQueue.isEmpty()){
//从任务队列中取出执行
Runnable r = taskQueue.poll();
if(null != r ) {
r.run();
System.out.println(" 当前执行第 [ "+count.incrementAndGet() +" ] 次任务" );
}
}
}
}
}
}
public void setIsRuning(){
this.isRuning = false;
}
}
}
- 测试类 Test.java
package com.zzq.core.pool;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.zzq.core.pool.ThreadPoolInterfaceImpl.WorkThread;
public class Test {
private static ExecutorService cachedThreadPool =Executors.newCachedThreadPool();
public static void main(String[] args) {
Runnable run = new Runnable() {
@Override
public void run() {
System.out.println("当前执行任务的线程名称"+ Thread.currentThread() + "---------");
}
};
Long starTime = System.currentTimeMillis();
ThreadPoolInterface ti = (ThreadPoolInterfaceImpl)new ThreadPoolInterfaceImpl();
for (int i = 0; i < 111111110; i++) {
ti.addWork(run);
}
System.out.println();
}
}
- 运行结果
推荐看看java连接池实现,这两篇都是池化技术,可能更容易理解线程池和连接池的区别和相近之处等等。代码或者我理解上有问题的地方,还请不吝指正。