常用线程池以及自定义线程池

自定义线程池

/**
 * @author Suny
 * @data 2022/1/6 10:12
 * @description 自定义线程池
 */
@Slf4j(topic = "PoolTest")
public class PoolTest {
    public static void main(String[] args) {
        ThreadPool threadPool = new ThreadPool(2, 1000L, TimeUnit.SECONDS, 10);
        for (int i = 0; i < 5; i++) {
            int j = i;
            threadPool.execute(()->{
              log.debug("当前线程{}",j);
            });
        }
    }
}

@Slf4j(topic = "ThreadPool")
class  ThreadPool{
    //任务队列
    private BlockingQueue<Runnable> taskQueue;

    //线程集合
    private HashSet<Worker> workers = new HashSet<>();

    //核心线程数
    private int coreSize;

    //获取任务的超时时间
    private Long timeOut;

    private TimeUnit timeUnit;

    public ThreadPool(int coreSize, Long timeOut, TimeUnit timeUnit,int QueueSize) {
        this.coreSize = coreSize;
        this.timeOut = timeOut;
        this.timeUnit = timeUnit;
        this.taskQueue = new BlockingQueue<>(QueueSize);
    }

    public void execute(Runnable runnable){
        //当任务数没有超过线程数则 直接执行如果超过放入队列进行等待
        synchronized (workers){
            if (workers.size()<coreSize) {
                Worker worker = new Worker(runnable);
                log.debug("添加执行线程{}",runnable);
                workers.add(worker);
                worker.start();
            }else{
                log.debug("等待执行线程{}",runnable);
                taskQueue.put(runnable);
                /*
                如果队列满了仍有任务需要进入队列进行等待
                    1、死等
                    2、带超时等待
                    3、让调用者放弃任务执行
                    4、让调用者抛出异常
                    5、让调用者自己执行任务
                 */
            }
        }
    }

    class Worker extends Thread{
        private Runnable task;
        public Worker(Runnable runnable){
            this.task = runnable;
        }

        @Override
        public void run() {
            //执行任务
            //1) 当task不为空 执行任务
            //2) 当task为空 查看任务队列
            //while (task != null || (task = taskQueue.task()) != null) {不设置获取任务的等待时间
            while (task != null || (task = taskQueue.poll(1000L,TimeUnit.SECONDS)) != null) {//设置获取任务的等待时间
                try {
                    log.debug("执行当前线程{}",task);
                    task.run();
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    task = null;
                }
            }

            synchronized (workers){
                //当前任务执行完之后删除
                log.debug("移除当前线程{}",task);
                workers.remove(this);
            }
        }
    }
}

class BlockingQueue<T>{
    public BlockingQueue(int cacheSize) {
        this.cacheSize = cacheSize;
    }

    //1、任务队列 底层是双向链表
    private Deque<T> queue = new ArrayDeque<>();

    //2、锁
    private ReentrantLock lock =  new ReentrantLock();

    //3、生产者的等待锁
    private Condition fullWaitSet = lock.newCondition();

    //6、消费者的等待锁
    private Condition emptyWaitSet = lock.newCondition();

    //7、线程池容量
    private int cacheSize;

    //11、获取队列中任务并设置超时时间
    @SneakyThrows
    public T poll(Long timeOut, TimeUnit unit){
        lock.lock();
        try {
            //将设置的超时时间转换为纳秒
            long nanos = unit.toNanos(timeOut);
            while (queue.isEmpty()){
                if (nanos <= 0){
                    return null;
                }
                //返回剩余的时间
                nanos = emptyWaitSet.awaitNanos(nanos);
            }
            T t = queue.removeFirst();
            fullWaitSet.signal();
            return t;
        }finally {
            lock.unlock();
        }

    }

    //8、获取队列中任务
    @SneakyThrows
    public T task(){
        lock.lock();
        try {
            while (queue.isEmpty()){
                emptyWaitSet.await();
            }
            T t = queue.removeFirst();
            fullWaitSet.signal();
            return t;
        }finally {
            lock.unlock();
        }

    }

    //9、往队列中添加任务
    @SneakyThrows
    public void put(T t){
        lock.lock();
        try {
            while (queue.size() == cacheSize){
                fullWaitSet.await();
            }
            queue.add(t);
            emptyWaitSet.signal();
        }finally {
            lock.unlock();
        }
    }

    //12、队列添加任务时设置超时时间
    @SneakyThrows
    public boolean offset(T t,Long timeOut,TimeUnit timeUnit){
        lock.lock();
        try {
            //将时间转换为纳秒
            long nanos = timeUnit.toNanos(timeOut);
            while (queue.size() == cacheSize){
                if (nanos <= 0){
                    return false;
                }
                nanos = fullWaitSet.awaitNanos(nanos);
            }
            queue.add(t);
            emptyWaitSet.signal();
            return  true;
        }finally {
            lock.unlock();
        }
    }

    //10、获取队列大小
    public int size(){
        lock.lock();
        try {
            return queue.size();
        }finally {
            lock.unlock();
        }
    }
}

线程池的状态和线程池的拒绝策略

线程池的状态
/*
 状态名      高3位     接收新任务   处理阻塞队列任务    说明
 RUNNING    111       Y           Y
 SHUTDOWN   000       N           Y               不会接收新任务,但会处理阻塞队列剩余任务
 STOP       001       N           N               会中断正在执行的任务,并抛弃阻塞队列任务
 TIDYING    010       -           -               任务全执行完毕,活动线程为0即进入终结
 TERMINATED 001       -           -               终结状态
 */
 JDK线程池的 拒绝策略
 1AbortPolicy 让调用者抛出RejectedExecutionException异常 默认策略
 2CallerRunsPolicy 让调用者运行任务
 3DiscardPolicy 放弃本次任务
 4DiscardOldestPolicy  放弃队列中最早的任务,让本任务取而代之

创建线程池

  /*
     参数
      1、核心线程数
      2、最大线程数
      3、救急线程的存活时间 (救急线程 = 最大线程数 - 核心线程数)
      4、救急线程的存活时间单位
      5、阻塞队列
       6、拒绝策略或者线程工厂作用就是给线程起一个方便查询的名字
*/
  new ThreadPoolExecutor(2,3,1000L, TimeUnit.SECONDS, new LinkedBlockingDeque<>());

固定线程数的线程池

/**
 * @author Suny
 * @data 2022/1/6 14:41
 * @description 固定线程数的线程池
 */
@Slf4j(topic = "ThreadPoolExecutorsTest")
public class ThreadPoolExecutorsTest {
    public static void main(String[] args) throws Exception {
        /**
         * 固定线程数,没有救急线程
         */
        ExecutorService pool = Executors.newFixedThreadPool(2, new ThreadFactory() {
            private AtomicInteger t = new AtomicInteger(0);
            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r,"MyPool_t" + t.getAndIncrement());
            }
        });
        pool.execute(()->{
            log.debug("1");
        });
        pool.execute(()->{
            log.debug("2");
        });
        pool.execute(()->{
            log.debug("3");
        });
        pool.shutdown();
    }
}

缓存线程池的创建

/**
 * @author Suny
 * @data 2022/1/6 14:50
 * @description 缓存线程池
 */
public class CacheThreadPoolTest {
    public static void main(String[] args) {
        /*
            缓存线程池,没有核心线程数,全部都是救急线程,救急线程存活时间60S
         */
        ExecutorService pool = Executors.newCachedThreadPool();
    }
}

单例线程池的创建

/**
 * @author Suny
 * @data 2022/1/6 14:56
 * @description 串行线程
 */
@Slf4j(topic = "SingleThreadExecutorTest")
public class SingleThreadExecutorTest {
    public static void main(String[] args) {
        /*
            单线程的线程池
         */
        ExecutorService service = Executors.newSingleThreadExecutor();

        service.execute(()->{
            log.debug("1");
            int i = 1 /0;
        });

        service.execute(()->{
            log.debug("2");
        });

        service.execute(()->{
            log.debug("3");
        });
    }
}

线程池的api

/**
 * @author Suny
 * @data 2022/1/6 15:11
 * @description 线程池的API测试
 */
@Slf4j(topic = "TestPool")
public class TestPool {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService pool = Executors.newFixedThreadPool(2);
        //提交单个任务
        Future<String> future = pool.submit(() -> {
            log.debug("有返回的线程执行");
            return "OK";
        });
        log.debug("{}",future.get());
        //提交多个任务
        List<Future<String>> list = pool.invokeAll(Arrays.asList(
                () -> {
                    log.debug("1");
                    Thread.sleep(1000L);
                    return "1";
                },
                () -> {
                    log.debug("1");
                    Thread.sleep(1500L);
                    return "2";
                },
                () -> {
                    log.debug("1");
                    Thread.sleep(2000L);
                    return "3";
                }
        ));
        list.forEach(s -> {
            try {
                log.debug("{}",s.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        });

        //那个线程最先运行完就获取那个线程的结果
        String result = pool.invokeAny(Arrays.asList(
                () -> {
                    log.debug("invokeAny1");
                    Thread.sleep(1000L);
                    return "invokeAny1";
                },
                () -> {
                    log.debug("invokeAny2");
                    Thread.sleep(1500L);
                    return "invokeAny2";
                },
                () -> {
                    log.debug("invokeAny3");
                    Thread.sleep(2000L);
                    return "invokeAny3";
                }
        ));
        log.debug("{}",result);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值