并发编程相关面试题(持续更新)

1.juc包提供了哪些工具?用在什么场景?

1.提供了比 synchronized 更加高级的各种同步结构,包括 CountDownLatchCyclicBarrierSemaphore 等
场景:可以实现更加丰富的多线程操作,比如利用 Semaphore 作为资源控制器,限制同时进行工作的线程数量。

2.各种线程安全的容器,比如最常见的 ConcurrentHashMap、有序的 ConcunrrentSkipListMap,或者通过类似快照机制,实现线程安全的动态数组 CopyOnWriteArrayList 等。

3.各种并发队列实现,如各种 BlockedQueue 实现,比较典型的 ArrayBlockingQueueSynchorousQueue 或针对特定场景的 PriorityBlockingQueue 等。

4.强大的 Executor 框架,可以创建各种不同类型的线程池,调度任务运行等,绝大部分情况下,不再需要自己从头实现线程池和任务调度器。

2.线程池有哪些定制参数?分别有什么作用?拒绝策略有哪些?哪种拒绝策略好?

'主要参数和作用'
1.corePoolSize
所谓的核心线程数,可以大致理解为长期驻留的线程数目(除非设置了 allowCoreThreadTimeOut)。对于不同的线程池,这个值可能会有很大区别,比如 newFixedThreadPool 会将其设置为 nThreads,而对于 newCachedThreadPool 则是为 02.maximumPoolSize,就是线程不够时能够创建的最大线程数。同样,对于 newFixedThreadPool,当然就是 nThreads,因为其要求是固定大小,而 newCachedThreadPool 则是 Integer.MAX_VALUE。

3.keepAliveTime 和 TimeUnit,这两个参数指定了额外的线程能够闲置多久。
如果一个线程空闲了keepAliveTime & TimeUnit这么久,而且线程池的线程数大于 corePoolSize ,那么这个空闲的线程就要被回收了。 

4.workQueue,工作队列,必须是 BlockingQueue5.threadFactory:通过这个参数你可以自定义如何创建线程,例如你可以给线程指定一个有意义的名字。

6.handler:通过这个参数你可以自定义任务的拒绝策略。如果线程池中所有的线程都在忙碌,并且工作队列也满了(前提是工作队列是有界队列),那么此时提交任务,线程池就会拒绝接收。至于拒绝的策略,可以通过 handler 这个参数来指定。


'4种拒接策略'1.CallerRunsPolicy:提交任务的线程自己去执行该任务。
2.AbortPolicy:默认的拒绝策略,会 throws RejectedExecutionException3.DiscardPolicy:直接丢弃任务,没有任何异常抛出。
4.DiscardOldestPolicy:丢弃最老的任务,其实就是把最早进入工作队列的任务丢弃,然后把新任务加入到工作队列。

Java1.6 版本还增加了 allowCoreThreadTimeOut(boolean value) 方法,它可以让所有线程都支持超时,这意味着如果项目很闲,就会将项目组的成员都撤走

'拒绝策略的选取':
具体要看执行的任务重要程度。如果是一些不重要任务,可以选择直接丢弃。
但是如果为重要任务,可以采用降级处理,例如将任务信息插入数据库或者消息队列,启用一个专门用作补偿的线程池去进行补偿

3.Executors提供了哪些类型的线程池?分别用于什么场景?使用线程池要注意些什么

Executors 目前提供了 5 种不同的线程池创建配置:
1.newCachedThreadPool():它是一种用来处理大量短时间工作任务的线程池,具有几个鲜明特点
(1)它会试图缓存线程并重用,当无缓存线程可用时,就会创建新的工作线程
(2)如果线程闲置的时间超过 60 秒,则被终止并移出缓存;
(3)时间闲置时,这种线程池,不会消耗什么资源。其内部使用 SynchronousQueue 作为工作队列。

2.newFixedThreadPool(int nThreads):重用指定数目(nThreads)的线程,其背后使用的是'无界的工作队列',任何时候最多有 nThreads 个工作线程是活动的
(1)如果任务数量超过了活动队列数目,将在工作队列中等待空闲线程出现
(2)如果有工作线程退出,将会有新的工作线程被创建,以补足指定的数目 nThreads。

3.newSingleThreadExecutor():
特点是工作线程数目被限制为 1,操作一个无界的工作队列,所以它保证了所有任务的都是被顺序执行,最多会有一个任务处于活动状态,并且不允许使用者改动线程池实例,因此可以避免其改变线程数目。

4.newSingleThreadScheduledExecutor()newScheduledThreadPool(int corePoolSize)
创建的是个 ScheduledExecutorService,可以进行定时或周期性的工作调度,区别在于单一工作线程还是多个工作线程。

5.newWorkStealingPool(int parallelism)
这是一个经常被人忽略的线程池,Java 8 才加入这个创建方法,其内部会构建ForkJoinPool,利用Work-Stealing算法,并行地处理任务,不保证处理顺序。

'不建议使用 Executors 的最重要的原因是':
1.Executors 提供的很多方法默认使用的都是无界的 LinkedBlockingQueue,高负载情境下,无界队列很容易导致 OOM,而 OOM 会导致所有请求都无法处理,这是致命问题。所以强烈建议使用有界队列。
2.使用有界队列,当任务过多时,线程池会触发执行拒绝策略,线程池默认的拒绝策略会 throw 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

酆都小菜鬼

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

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

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

打赏作者

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

抵扣说明:

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

余额充值