校招刷题群
高效刷题 迎战校招
校招精选试题
近年面笔经面经群内分享
Java刷题群 前端刷题群 产品运营群
首页 > java语言 > 线程池
题目

线程池中的线程是怎么创建的?是一开始就随着线程池的启动创建好的吗?

解答

线程池中的线程是在第一次提交任务submit时创建的

创建线程的方式有继承Thread和实现Runnable,重写run方法,start开始执行,wait等待,sleep休眠,shutdown停止。

(1)newSingleThreadExecutor:单线程池。

顾名思义就是一个池中只有一个线程在运行,该线程永不超时,而且由于是一个线程,当有多个任务需要处理时,会将它们放置到一个无界阻塞队列中逐个处理,它的实现代码如下:

1
2
3
4
5
public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,
             new LinkedBlockingQueue<Runnable()));
}

它的使用方法也很简单,下面是简单的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void main(String[] args) throws ExecutionException,InterruptedException {
    // 创建单线程执行器
    ExecutorService es = Executors.newSingleThreadExecutor();
    // 执行一个任务
    Future<String> future = es.submit(new Callable<String>() {
        @Override
        public String call() throws Exception {
            return "";
        }
    });
    // 获得任务执行后的返回值
    System.out.println("返回值:" + future.get());
    // 关闭执行器
    es.shutdown();
}

(2)newCachedThreadPool:缓冲功能的线程。

建立了一个线程池,而且线程数量是没有限制的(当然,不能超过Integer的最大值),新增一个任务即有一个线程处理,或者复用之前空闲的线程,或者重亲启动一个线程,但是一旦一个线程在60秒内一直处于等待状态时(也就是一分钟无事可做),则会被终止,其源码如下:

1
2
3
4
public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
}

这里需要说明的是,任务队列使用了同步阻塞队列,这意味着向队列中加入一个元素,即可唤醒一个线程(新创建的线程或复用空闲线程来处理),这种队列已经没有队列深度的概念了。

(3)newFixedThreadPool:固定线程数量的线程池。

在初始化时已经决定了线程的最大数量,若任务添加的能力超出了线程的处理能力,则建立阻塞队列容纳多余的任务,其源码如下: 

1
2
3
4
5
public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
}

上面返回的是一个ThreadPoolExecutor,它的corePoolSize和maximumPoolSize是相等的,也就是说,最大线程数量为nThreads。如果任务增长的速度非常快,超过了LinkedBlockingQuene的最大容量(Integer的最大值),那此时会如何处理呢?会按照ThreadPoolExecutor默认的拒绝策略(默认是DiscardPolicy,直接丢弃)来处理。

以上三种线程池执行器都是ThreadPoolExecutor的简化版,目的是帮助开发人员屏蔽过得线程细节,简化多线程开发。当需要运行异步任务时,可以直接通过Executors获得一个线程池,然后运行任务,不需要关注ThreadPoolExecutor的一系列参数时什么含义。当然,有时候这三个线程不能满足要求,此时则可以直接操作ThreadPoolExecutor来实现复杂的多线程计算。

newSingleThreadExecutor、newCachedThreadPool、newFixedThreadPool是线程池的简化版,而ThreadPoolExecutor则是旗舰版___简化版容易操作,需要了解的知识相对少些,方便使用,而旗舰版功能齐全,适用面广,难以驾驭。

C 0条回复 评论

帖子还没人回复快来抢沙发