简单线程池的实现

本篇主要用作链接使用。

线程池的核心就是,当接收到一个任务,需要一个线程去执行时,并不着急创建一个线程,而是先去线程池检查是否有空闲的线程,如果有,则直接使用,如果没有则创建新的线程,然后执行任务。任务执行完成后,也不着急销毁线程,而是将线程放到线程池的空闲队列中,等待下次使用。 首先是线程池的实现。

首先是线程池的实现:

/**
 * Created by Joker on 2015/3/7.
 */
 public class ThreadPool {
 private static ThreadPool instance = null;
 //空闲的线程队列
 private List<JThread> idleThreads;
 //已有的线程总数
 private int threadCounter = 0;
 private Boolean isShunDown = false;
 public ThreadPool() {
     //初始化空闲线程队列容量为5
     this.idleThreads = new Vector<JThread>(5);
     this.threadCounter = 0;
 }
 private static class SingleTonHolder {
     private static ThreadPool threadPool = new ThreadPool();
 }
 /*单例获得线程池实例*/
 public static ThreadPool getInstance() {
     return SingleTonHolder.threadPool;
 }
 public int getThreadCounter() {
     return threadCounter;
 }

 /**
  * 将线程放入池中,回收线程
  */
 protected synchronized void repool(JThread repoolingThread) {
     if (!isShunDown) {
         idleThreads.add(repoolingThread);
     } else {
         repoolingThread.shutDown();
     }
 }
 /**
  * 停止池中所有线程
  */
 public synchronized void shutDownAll() {
     this.isShunDown = true;
     for (JThread jThread : idleThreads) {
         jThread.shutDown();
     }
 }

 /**
  * 执行线程任务
  */
 public synchronized void execute(Runnable target) {
     this.isShunDown = false;
     JThread jThread = null;
     /*如果池中有空余线程,直接使用该线程*/
     if (idleThreads.size() > 0) {
         jThread = idleThreads.get(idleThreads.size() - 1);
         //将该线程从池中移除
         idleThreads.remove(jThread);
         //立即执行该任务
         jThread.setTarget(target);
     }
     /*没有空闲线程,创建新线程*/
     else {
         threadCounter++;
         //创建线程
         jThread = new JThread(target, "JThread:" + threadCounter, ThreadPool.this);
         jThread.start();
     }
 }
}

要使用上述线程池,还需要一个永不退出的工作现场与之配合。是一个While循环,手动关闭之前,永不结束,一直等待新的任务进来。

该工作线程的实现如下:

/**
 * Created by Joker on 2015/3/7.
 */
 public class JThread extends Thread {
 //线程池
 private ThreadPool threadPool;
 //任务
 private Runnable target;
 private boolean isShutDown = false;
 private boolean isIdle = false;
 public JThread(Runnable target, String name, ThreadPool threadPool) {
     super(name);
     this.target = target;
     this.threadPool = threadPool;
 }
 public Runnable getTarget() {
     return target;
 }
 public boolean isIdle() {
     return isIdle;
 }

 @Override
 public void run() {
     //只要没有关闭,则一直不结束该线程
     while (!isShutDown) {
         isIdle = false;
         if (null != target) {
             //执行任务,注意这里调用的是run(),而不是start()
             target.run();
         }
         //任务结束,闲置状态
         isIdle = true;
         try {
             threadPool.repool(JThread.this);
             synchronized (this) {
                 //线程空闲,等待新的任务到来
                 wait();
             }
         } catch (InterruptedException e) {
         }
         isIdle = false;
     }
 }

 public synchronized void setTarget(Runnable target) {
     this.isShutDown = false;
     this.target = target;
     //设置任务之后,通知run方法,开始执行任务
     notifyAll();
 }

 /**
  * 关闭线程
  */
 public synchronized void shutDown() {
     this.isShutDown = true;
    notifyAll();
 }
}

使用方法如下:

ThreadPool.getInstance().execute(new Runnable() {
            @Override
            public void run() {
                /*执行任务*/
            }
        });

在线程频繁调度时,通过线程的复用,对性能的提升有很大的帮助

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • About ExecutorService(2),自定义线程池

    琢磨了一下,还是把这篇提前了,本片篇幅可能会有些长,甚至冗余,请各位看官原谅我这拙劣的写作能力。

    小鄧子
  • About ExecutorService(4),AsyncTask番外篇

    直接切入正题,我们都知道AT在3.X将默认的线程池由并行改为串行,真的是众所周知的3.0(HONEYCOMB)开始的嘛?答案是否定的。确切的说是从3.2(HON...

    小鄧子
  • 算法与数据结构(2),Map

    睡了不到六个小时,被一个很奇葩又很奇怪的梦吓醒,以最快的速度穿好衣服,跑下楼去买了杯咖啡上来,文字没写多少,咖啡倒是一饮而尽。

    小鄧子
  • Java多线程Thread VS Runnable详解

    进程是程序在处理机中的一次运行。一个进程既包括其所要执行的指令,也包括了执行指令所需的系统资源,不同进程所占用的系统资源相对独立。所以进程是重量级的任务,它们之...

    Java后端工程师
  • JVM内存模型和性能优化之线程锁优化(下篇)

    当一个线程更新了自己工作内存中的数据后,没有写到主内存,其他线程是不知道的。 (1)顺序一致性模型: 要求对改变的值立即进行传播, 并确保该值被所有...

    lyb-geek
  • 并发编程

    线程安全 线程安全概念 : 当多个线程访问某一个类(对象或方法)时,这个类始终都能表现出正确的行为,那么这个类(对象或方法)就是线程安全的. ...

    海仔
  • 【转】Java并发的AQS原理详解

    每一个 Java 的高级程序员在体验过多线程程序开发之后,都需要问自己一个问题,Java 内置的锁是如何实现的?最常用的最简单的锁要数 ReentrantL...

    一枝花算不算浪漫
  • 打通 Java 任督二脉 —— 并发数据结构的基石

    每一个 Java 的高级程序员在体验过多线程程序开发之后,都需要问自己一个问题,Java 内置的锁是如何实现的?最常用的最简单的锁要数 ReentrantLoc...

    老钱
  • Java 经典问题

    switch语句后的控制表达式只能是short、char、int、long整数类型和枚举类型,不能是float,double和boolean类型。String类...

    好好学java
  • 教妹学 Java:难以驾驭的多线程

    “二哥,上一篇《集合》的反响效果怎么样啊?”三妹对她提议的《教妹学 Java》专栏很关心。

    沉默王二

扫码关注云+社区

领取腾讯云代金券