java线程(1) —— 自定义线程池(2)

java线程(1) —— 自定义线程池(2)

上篇文章存在的问题

  • put方法没有超时等待,如果消息队列没有消费,
  • 如果消息队列一直是满的,生产者应该是什么操作,有以下的几种策略
    • 超时等待
    • 让调用者放弃任务执行
    • 死等
    • 让调用者抛出异常
    • 让调用者自己执行任务
      上面所说的这些个策略,如果按照之前的if else 写 就很烦。将这个什么策略。让调用者来实现。在这里实现一个接口,将实现方式给调用者给。
1. 超时等待
  public void push(T task, long awaitTime, TimeUnit unit) {
        /*
        流程
        - 判断满不满
        - 不满就放,满就等待
        - 唤醒等待线程
         */

        //上锁
        lock.lock();
        try {
            //时间单位变为一样 nanos
            long l = unit.toNanos(awaitTime);
            while (capcity == deque.size()) {
                try {
                    log.debug("队列已经满,fullwaitset:{}", fullWaitSet);
                    //超时等待
                    l = fullWaitSet.awaitNanos(l);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            deque.addLast(task);
            emptyWaitSet.signalAll();

        } finally {
            lock.unlock();
        }
    }
2. 策略模式(由调用者决定)

写一个函数式的接口

//函数式接口
@FunctionalInterface
interface RejectPolicy<T>{
    /**
     * 在创建线程池的时候将代码执行什么策略
     * @param queue
     * @param task
     */
    void reject(BlockQueue<T> queue, T task);
}

** 在消息队列中写一个tryPut方法**

/**
     * 尝试获取锁
     * @param rejectPolicy      策略
     * @param task              任务对象
     */
    public void  tryPut(RejectPolicy rejectPolicy,T task){
            /*
        流程
        - 判断满不满
        - 不满就放,满就等待
        - 唤醒等待线程
         */

        //上锁
        lock.lock();
        try {
            //时间单位变为一样 nanos
            while (capcity == deque.size()) {
                log.debug("队列已经满, stackDeque:{}",task);
                //这里执行调用者传过来的代码
                rejectPolicy.reject(this,task);
            }
            deque.addLast(task);
            emptyWaitSet.signalAll();

        } finally {
            lock.unlock();
        }
    }

修改线程池的execute方法

 /**
     * 线程池 执行任务的方法
     *
     * @param task 需要执行的任务
     */
    public void execute(Runnable task) {
        /**
         * 创建线程执行任务.
         * 懒惰初始化;
         *   - 如果workset的数量小于coresize 那就创建,执行任务
         *   - 否则:任务进任务队列
         *  这里要加锁:因为work是公用的,
         */
        synchronized (works) {
            if (works.size() < coreSize) {
                //创建
                Work work = new Work(task);
                // 添加线程进works集合
                works.add(work);
                //开启线程
                work.start();
            } else {
                //任务进消息队列
                taskQueue.tryPut(rejectPolicy,task);  // 主要修改的是这里
            }
        }
    }

测试

 public static void main(String[] args) {
        ThreadPool threadPool = new ThreadPool(1, 1, 1000L, TimeUnit.SECONDS,(blockQueue,task)->{
            //死等
            blockQueue.put(task);

        });
        for (int i = 0; i < 3; i++) {
            int j = i;
            threadPool.execute(()->{
                try {
                    TimeUnit.SECONDS.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                log.debug("{}",j);
            });
        }
    }

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值