线程池详解

线程池

  • 在Java中线程池被称为ExecutorService(执行服务)但是在底层还是被称为ThreadPools

Executor框架创建线程池

Executor框架包括:线程池、Executor、Executors、ExecutorService、 CompletionService,Future,Callable 等

通过Executors类中提供的一个方法newFixedThreadPool得到一个线程对象

我们首先来看一下整个Executors创建线程池的体系

在这里插入图片描述

1.public static ExecutorService newFixedThreadPool(int nThreads): 创建一个线程池并返回

2.同样也可以直接创建ThreadPooExecutor对象并注入参数即可

/* 格式如下: */
ThreadPoolExecutor executor = new ThreadPoolExecutor(
					corePoolSize核心线程数,
					maxmumPoolSize最大线程数,
					keepAliveTime普通线程存活时间,
					unit时间单位,
					BlockQueue组赛队列,
					handler拒绝提交任务异常);	

Executers提供静态方法–>newFixedThreadPool()—>底层由ThreadPoolExecutor实现

首先我们先看一下newFixedThreadPool的底层实现

newFixedThreadPool源码:
        public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
				0L, TimeUnit.MILLISECONDS,
				new LinkedBlockingQueue<Runnable>());
        }
/*可以看出在newFixedThreadPool的底层依然是创建了 ThreadPoolExecutor(线程执行器)

下面再看一下ThreadPoolExecutor的底层

那么下面我们再来看一看ThreadPoolExecutor的源码:
        public ThreadPoolExecutor(int corePoolSize,  //--->核心线程(线程池保留这个数量的线程不死)
int maximumPoolSize,   //--->最大线程(线程池所支持的做多线程数量)假设核心线程3最大线程10则有7个线程用完就会死
long keepAliveTime,    //--->线程保持存活时间(KeepAliveTime就是闲置的线程等待的最长时间,超过这个时间改线程就会消亡)
TimeUnit unit,         //--->时间单位
BlockingQueue<Runnable> workQueue//--->(阻塞队列)等待队列,正在排队等待执行的线程存放在该队列中等待线程执行
                              ) {
        this(corePoolSize, maximumPoolSize, 						 keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), 			  			   defaultHandler);
        }

​ 创建线程池,我们已经指定了核心线程为3,其他在为指定的条件下均为默认情况,此时我们添加三个任务均会创建新县城执行,但是添加第四个任务时就不会再创建新的线程,但是具体是由哪个线程执行第四个任务具体还要看线程调度的安排

public class _2 {
    public static void main(String[] args) {
        /* 1. 创建线程池,此处只指定了线程数,其余均为默认*/
        ExecutorService pools = Executors.newFixedThreadPool(3);
        /* 3. 添加任务到线程池 */
        MyRunnable task = new MyRunnable();
        pools.execute(task);//第一次提交任务,线程池此时创建新线程
        pools.execute(task);//第二次提交任务,线程池此时创建新线程
        pools.execute(task);//第三次提交任务,线程池此时创建新线程
        pools.execute(task);//第四次提交任务,复用之前的线程

    }
    }
        /* 2. 创建线程任务类  此处用于给线程池添加任务 */
    class MyRunnable implements Runnable{
        @Override
        public void run() {
            for (int i = 1; i <= 3; i++) {
                System.out.println(Thread.currentThread().getName()+"--->"+i);
            }
        }
    }

ThreadPool执行Callable任务

​ 此时我们将Runnable和Callable两种线程任务类做出对比

public class Demoo {
    public static void main(String[] args) {
        /* 1. 创建线程池--->核心线程数为3 */
        ExecutorService pools = Executors.newFixedThreadPool(3);
        /* 2. 创建Callable任务并添加到线程池中 */
        MyCallable mc = new MyCallable();
        try {
            System.out.println(pools.submit(mc).get());
            /*调用submit返回的是一个Future类实例,故而可以直接调用get方法来获取返回值
            //此处体现Callable的优越性,可以得到返回的结果
             */
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class MyCallable implements Callable<String>{
    @Override
    public String call() throws InterruptedException {
        //此处体现Callable可以直接抛出异常的优越性
        Thread.sleep(1000);
        return "call方法体执行中...";
    }
}

详解submit()和execute()方法

浅谈一下向线程池添加任务的两种方法submit()和execute()

submit():用于添加带有返回值的任务—>例如Callable任务
也可以用于提交Runnable不带返回值的任务
通过获取返回值结果可以确定线程池执行此任务是否成功
submit()会得到线程池返回的一个Future对象,可以直接调用get()方法来获取线程任务返回值

下面我们来看一下submit()方法源码

/* 在接口ExecutorService中声明 */
<T> Future<T> submit(Callable<T> task);
/* 下面看在AbstractExecutorService实现方法的方法体 */
public <T> Future<T> submit(Callable<T> task) {
     if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task);
                        execute(ftask);
                        return ftask;
    		//此处返回的ftask是Fture的一个对象
                    }
//再看RunnableFuture继承了Future类
public class FutureTask<V> implements RunnableFuture<V> 
public interface RunnableFuture<V> extends Runnable, Future<V>
/*
综上我们可以得出它最终返回了一个Future的实例*/

execute():用于提交不需要返回值的任务—>例如Runnable任务 因此并不能判断我们的线程池是否执行成功

关闭线程池

pools.shutdown();//等线程池任务执行完毕就会关闭
pools.shutdownNow();//立即关闭线程池,不论任务是否执行完毕
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

绿仔牛奶_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值