多线程模拟线程池

4 篇文章 0 订阅
2 篇文章 0 订阅

直接上图

1. 线程池是干什么的 :

线程池是利用已有的线程处理任务, 避免频繁创建线程浪费cpu性能。这里不得不提一嘴,将线程和任务分开的设计方案在多线程里面是十分好用的设计。

2.设计概述:

ThreadPool:线程池,存放线程的地方

阻塞队列 :存放任务的地方 ,此处的设计是利用队尾队列,将放入任务,对头出任务,让线程池中拿出一个线程处理任务。利用队列的设计可以满足先来的任务先执行。

具有取出任务 ,加入任务的功能

3.代码实现

(1)阻塞队列

属性分析:

1.dqueque:队列,里面可以真正的存放任务的地方 

2.lock:ReentrantLock锁,这种锁的好处是可以,设计不同的等待条件,可以锁住和释放对于不同等待条件的线程。就把他看做一个锁就行 。

3.fullWaitSet:一种锁 , 线程增加任务的时候发现  ,任务队列满了,便锁住线程也可以设置超时等待。

4.emptyWaitSet:同上 ,取出任务的时候,针对队伍为空
5.capacity:队伍容纳量

方法分析:

1.ThreadPool:构造方法 ,可以设置队伍容纳量

2.take: 让线程从任务队列取出任务。

  public T take(){
        //加锁,避免多个线程同时取一个任务
        lock.lock();

        try{
            //队列为空,线程进入等待
             while (deque.isEmpty()){
                 try {
                     //线程进入 等待
                     emptyWaitSet.await();
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 }
             }
             //队伍不为空,移除队头元素
            T task = deque.removeFirst();
             //唤醒 所有因为队列为满而不能添加元素的线程  
             fullWaitSet.signalAll();
             return task ;
        }finally {
            //锁释放
            lock.unlock();
        }
    }

3.pull:take方法的改进 增加超时等待功能。

       设置超时等待:

        1.当任务数量过多,线程将多余的任务放入任务队列 

        2.当任务队列为空,自己也把任务执行完了,线程帮队列释放该任务

    //超时等待的方法
    public T pull(long timeOut, TimeUnit unit){
        lock.lock();

        try{
            //将时间转化为纳秒
            long waitTime = unit.toNanos(timeOut);
            //队列为空
            while (deque.isEmpty()){
                try {
                    //超时
                    if (waitTime <= 0){
                        return null ;
                    }

                    //awaitNanos方法会自动减少timeOut,并返回还需要等待的时间
                    waitTime = emptyWaitSet.awaitNanos(timeOut);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //移除对头元素
            T task = deque.removeFirst();
            fullWaitSet.signalAll();
            return task ;
        }finally {
            lock.unlock();
        }
    }

4.put:放入任务的方法:其实也可以设计超时等待

 public void put(T task){
       lock.lock();
        //队列为空
        try{
            while (deque.size() >= capacity){
                try {
                    //队列满了,让 想在队伍放入任务的 线程等一下
                    fullWaitSet.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //not
            deque.addLast(task);
            emptyWaitSet.signalAll();
        }finally {
            lock.unlock();
        }
    }

5.size:返回队伍任务数量,也需要加锁,有可能造成关于 读 的并发问题

线程池:

  属性分析

1.taskQuue:阻塞队列, 线程需要从任务队列拿和放入任务

2.workers:可以执行的任务对象 (属于Work类的哈希set)

3.coreSize :线程数量

4.timeOut:超时等待时间

方法分析

execute(主要方法):1.线程将方法放入队列
         2.执行任务
加锁避免并发造成多个任务往同一个地方加入任务,其实
 //执行任务
    public void execute(Runnable task){
        //任务数量没有超过线程数量 ,交给 work执行
        //else
        //任务数超过coreSize的时候 加入任务队列暂存
          synchronized (workers){
              if (workers.size() < coreSize){
                  Worker worker = new Worker(task);
                  log.debug("新增work",worker);
                  worker.start();
                  workers.add(worker) ;
              }else {
                  log.debug("加入任务队列",task);
                  taskQuue.put(task);
              }
          }

    }

work类:是任务类继承Thead方法, 实现run接口 ,运行run接口就是一个线程了。 

测试类

public class Test01 {
    public static void main(String[] args) {
       ThreadPool pool =   new ThreadPool(2,1000,TimeUnit.MILLISECONDS,10);
        for (int i = 0; i < 3; i++) {
           int j = i;
            pool.execute(()->{
                log.debug("正在执行任务...{}",j);
            });
        }

    }
}

pool:最多两个线程

for: 搞了三个任务

测试结果

后面还可以采取策略模式对 队列新增任务 进行改进,松一下耦合度

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值