并发编程面试题归纳总结

1.为什么要用线程池?

1.使用起来方便快捷
2.相比较于传统开启线程的方式,效率得到极大的提高,下面的代码可以证明

package xu.ba.dou;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * @Package xu.ba.dou
 * @Author 徐八斗
 * @Date 2021/7/3 9:55
 * @Version V1.0
 */
public class ThreadPoolTest {
    public static void main(String[] args) throws InterruptedException {
        simpleTest();
        threadPoolTest();
    }

    /**
     * 普通的开启线程的方式
     */
    public static void simpleTest() throws InterruptedException {
        long beginTime  = System.currentTimeMillis();
        List<Integer> list = new ArrayList<>();
        Random rand = new Random(47);
        for (int i = 0; i < 100000; i++) {
            Thread thread = new Thread(() -> {
                list.add(rand.nextInt());
            });
            thread.start();
            thread.join();
        }
        long endTime = System.currentTimeMillis();
        System.out.println(String.format("普通的开启线程的方式总共花了 %s ms", endTime - beginTime));
    }

    /**
     * 通过线程池开启线程的方式
     */
    public static void threadPoolTest() throws InterruptedException {
        long beginTime  = System.currentTimeMillis();
        List<Integer> list = new ArrayList<>();
        Random rand = new Random(47);
        ExecutorService exec = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 100000; i++) {
            exec.execute(() -> {
                list.add(rand.nextInt());
            });
        }
        exec.shutdown();
        exec.awaitTermination(1, TimeUnit.DAYS);
        long endTime = System.currentTimeMillis();
        System.out.println(String.format("线程池开启线程的方式总共花了 %s ms", endTime - beginTime));
    }
}

执行结果如下所示
在这里插入图片描述
通过上面的例子,可以看到,使用线程池开启线程之后,速度得到了质的飞越

2.线程池构造器中各个参数的含义是什么?

直接上源码

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

int corePoolSize 核心线程数
int maximumPoolSize 最大线程数
long keepAliveTime 非核心线程(最大线程-核心线程)的存活时间(核心线程一直存在,所以该字段对核心线程不起作用)
TimeUnit unit 存活时间的单位
BlockingQueue workQueue 存放任务的阻塞队列
ThreadFactory threadFactory 生产线程的工厂
RejectedExecutionHandler handler 拒绝策略

3.常见的线程池有哪些,区别是什么?

上源码

public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>(),
                                      threadFactory);
    }
public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

常见的线程池就是上面这三种
1.固定数量的线程池
核心线程数和最大线程数相等,队列使用无界阻塞队列,故而超出核心线程数的任务都会直接进入无界队列里
2.固定数量为1的单线程的线程池
核心线程数和最大线程数都是1,队列使用无界阻塞队列
3.缓存线程池
核心线程数为0,最大线程数是整型的最大值,队列使用的同步队列(只能存放一个任务)

4.为什么要使用自定义的线程池?

很明显上面三种常用的线程池都存在着一些问题
固定数据的线程池和单线程线程池都使用的是无界队列,那么当任务不断的添加,就有可能会导致内存溢出
而缓存线程池,由于随着任务的不断添加,会不断的添加线程,那么就会增加cpu的负担(因为要不断的切换来,切换去)
所以当我们使用线程池的时候,最后是能根据自己的需求去自定义一个线程池(如何定义,可参考上面的线程池构造方法的参数)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

zane0

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

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

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

打赏作者

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

抵扣说明:

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

余额充值