JAVA多线程学习------线程池原理

本文详细介绍了如何实现一个简单的线程池,包括堵塞队列、线程池类以及拒绝策略接口。线程池通过控制核心线程数和任务队列来管理任务执行,并提供了自定义的拒绝策略。同时,对比了JDK中的ThreadPoolExecutor,分析了其构造参数、线程池状态以及不同类型的线程池实例。最后,展示了使用ScheduledThreadPoolExecutor设置定时任务的例子。
摘要由CSDN通过智能技术生成

 1.简单线程池的实现(含有简单的拒绝策略)

1.1 堵塞队列

package com.xjq.ThreadPool;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/*
任务堵塞队列
 */
public class BlockingQueue<T> {
    private int capecity;    //堵塞队列容量
    private Deque<T> queue;   //双向链表
    private ReentrantLock lock = new ReentrantLock();  //lock 锁
    private Condition fullWaitSet = lock.newCondition();    //队列满时的条件变量
    private Condition emptyWaitSet = lock.newCondition();    //队列空时的条件变量

    public BlockingQueue(int capecity){
        this.capecity = capecity;
        this.queue = new ArrayDeque<>(capecity);
    }

    //堵塞队列获取元素
    public T take(){
        lock.lock();
        try{
            while(queue.isEmpty()){
                try {
                    emptyWaitSet.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            T t = queue.removeFirst();
            fullWaitSet.signal();
            return t;
        }finally {
            lock.unlock();
        }


    }
    /**
     * 含有等待时间的获取
     */
    public T poll(long times,TimeUnit timeUnit){
        lock.lock();
        long timeNs = timeUnit.toNanos(times);   //时间统一转换为ns
        try{
            while(queue.isEmpty()){
                try {
                    if (timeNs <= 0){
                        return null;
                    }
                    timeNs = emptyWaitSet.awaitNanos(timeNs);   //返回剩余的等待时间
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            T t =  queue.removeFirst();
            fullWaitSet.signal();
            return t;
        }finally {
            lock.unlock();
        }
    }

    /**
     * 堵塞队列添加元素
     */
    public void put(T t){
        lock.lock();
        try{
            while(queue.size() == capecity){
                try {
                    fullWaitSet.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            queue.addLast(t);
            emptyWaitSet.signalAll();
            System.out.println(Thread.currentThread().getName()+"进入堵塞队列");
        }finally {
            lock.unlock();
        }
    }

    /**
     * 具有超时时间的插入堵塞队列
     * @param task    任务
     * @param time    时间
     * @param timeUnit   时间单位
     */
    public void offer(T task,long time,TimeUnit timeUnit){
        lock.lock();
        try {
            long nanos = timeUnit.toNanos(time);
            while(queue.size() == capecity){
                try {
                    if (nanos <= 0){
                        System.out.println("超时,加入堵塞队列失败。。");
                        return;
                    }
                    nanos = fullWaitSet.awaitNanos(nanos);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            queue.addLast(task);
            emptyWaitSet.signalAll();
        }finally {
            lock.unlock();
        }
    }
    /**
     * 实现拒绝策略
     */
    public void tryPut(RejectPoliy rejectPoliy,T task){
        lock.lock();
        try {
            if(queue.size() == capecity){
                rejectPoliy.reject(this,task);
            }else {
                System.out.println("加入到堵塞队列。。。");
                queue.addLast(task);
                emptyWaitSet.signalAll();
            }
        }finally {
            lock.unlock();
        }
    }


}

1.2 线程池

package com.xjq.ThreadPool;


import java.util.HashSet;
import java.util.concurrent.TimeUnit;

public class ThreadPool {
    private BlockingQueue<Runnable> tasks;     //堵塞队列
    private HashSet<worker> workers = new HashSet<>();    //线程集合
    private int capecity;    //堵塞队列的容量
    private int coreSize;     //线程核心数
    private long time;         //设置超时时间
    private TimeUnit timeUnit;   //时间单位
    private RejectPoliy<Runnable> rejectPoliy;
    public ThreadPool(int coreSize, int capecity, long time, TimeUnit timeUnit,RejectPoliy<Runnable> rejectPoliy){
        this.coreSize = coreSize;
        this.capecity = capecity;
        this.tasks = new BlockingQueue<>(capecity);
        this.time = time;
        this.timeUnit = timeUnit;
        this.rejectPoliy = rejectPoliy;
    }

    /**
     * 当线程数小于coreSize时,创建新的worker线程,加入到线程集合中。
     * 否则,吧task任务加入到堵塞队列。
     * @param task
     */
    public void execute(Runnable task){
        synchronized (workers){
            if(workers.size() < coreSize){
                worker w = new worker(task);
                System.out.println("创建一个works");
                workers.add(w);
                w.start();
            }else {
                tasks.tryPut(rejectPoliy,task);
            }
        }
    }

    /**
     * 执行的任务抽象类
     */
    class worker extends Thread{
        private Runnable task;
        public worker(Runnable task){
            this.task = task;
        }

        /**
         * 1.当task不为空时,执行task,执行完task的run方法后,task置为空
         * 2.当task执行完后继续去堵塞队列获取任务继续执行。
         */
        @Override
        public void run() {
            while(task != null || (task = tasks.poll(time,timeUnit)) != null){
                try{
                    task.run();
                    System.out.println("开始执行"+Thread.currentThread().getName());
                }catch (Exception e) {

                }finally {
                    task = null;
                }
            }
            //work 线程结束后,从workers集合中移除
            synchronized (workers){
                workers.remove(this);
                System.out.println("work线程结束。。。");
            }
        }
    }
}

1.3 拒绝策略接口

package com.xjq.ThreadPool;
@FunctionalInterface      //可以使用lamb表达式
public interface RejectPoliy<T> {
    /**
     * 用户自定义拒绝策略 
     * @param queue    任务堵塞队列
     * @param task     待执行的任务
     */
    void reject(BlockingQueue<T> queue,T task);
}

1.4 测试类

package com.xjq.ThreadPool;

import java.util.concurrent.TimeUnit;

public class TestPool {
    public static void main(String[] args) {
        ThreadPool pool = new ThreadPool(2,2,
                1, TimeUnit.SECONDS,
                (queue,task)->{
                    //四种自定义拒绝策略
                    //1.死等
                    //queue.put(task);
                    //2.超时放弃等待
                   // queue.offer(task,2,TimeUnit.SECONDS);
                    //3.调用者放弃执行任务
                    //
                    //4.调用者执行这个任务
                    task.run();
                });
        for (int i = 0; i < 5; i++) {
            int num = i;
                pool.execute(()->{
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(num);
                });

        }
    }
}

2. JDK中的线程池

2.1线程池类

2.2 线程池类构造方法

 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)

corePoolSize:指定了线程池中的核心线程数量,它的数量决定了添加的任务是开辟新的线程去执行,还是放到workQueue任务队列中去;

maximumPoolSize:指定了线程池中的最大线程数量,这个参数会根据你使用的workQueue任务队列的类型,决定线程池会开辟的最大线程数量;

其中含有救急线程,救急线程数=最大线程数 - 核心线程数。当新来一个任务,核心线程数和堵塞队列都满时,就会创建救急线程。

keepAliveTime:当救急线程没有任务执行时,存活时间。;

unit:keepAliveTime的单位

workQueue:任务队列,被添加到线程池中,但尚未被执行的任务;它一般分为直接提交队列、有界任务队列、无界任务队列、优先任务队列几种;

threadFactory:线程工厂,用于创建线程,一般用默认即可;

handler:拒绝策略;当任务太多来不及处理时,如何拒绝任务;

2.3 线程池状态

 3.线程池实例

3.1 NewFixedThreadPool

3.2 newCachedThreadPool

3.3 newSingleThreadPool

3.4 总结

4.线程池应用-----设置定时任务

public class TimeWork {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();   //获取当前时间   2020-10-16T17:28:14.413
        //LocalDateTime  可以设置时间
        LocalDateTime time = now.withHour(9).withMinute(52).withSecond(0).with(DayOfWeek.SATURDAY);  //设置时间为本周六的9:52:0

        if(time.compareTo(now) < 0){      //比较当前时间和设置的时间的天数差值
            time  = time.plusWeeks(1);     //时间往后推一周
        }
        Duration duration = Duration.between(now,time);    //设置两个时间的间隔
        long initDely = duration.toMillis();        //把时间间隔转换为毫秒
        System.out.println(initDely);
        ScheduledThreadPoolExecutor deleyRun = new ScheduledThreadPoolExecutor(2);    //带有定时任务的线程池对象
        deleyRun.scheduleWithFixedDelay(
            ()->{
            System.out.println("1");
                },                  //Runable  接口对象
                initDely,           //延迟多久开始执行程序
                1000,         //任务间隔多久重复执行
                TimeUnit.MILLISECONDS);   //时间单位
        System.out.println(time);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值