第二季:8.线程池用过吗? ThreadPoolExecutor谈谈你的理解?【Java面试题】

简介: 第二季:8.线程池用过吗? ThreadPoolExecutor谈谈你的理解?【Java面试题】

前言


2022 10/10 21:22

路漫漫其修远兮,吾将上下而求索


本文是根据尚硅谷学习所做笔记

仅供学习交流使用,转载注明出处

推荐

尚硅谷Java大厂面试题第2季,面试必刷,跳槽大厂神器

第二季大佬总结

8.线程池用过吗? ThreadPoolExecutor谈谈你的理解?

说明

本文目录前是相关视频的名字和具体视频中思维导图的名字

题目

8.线程池用过吗? ThreadPoolExecutor谈谈你的理解?

说说线程池的底层工作原理?

45 Callable接口

package blockingqueue7;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
class MyThread implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        System.out.println(Thread.currentThread().getName()+"********come in Callable");
        return 1024;
    }
}
/**
 * @author CSDN@日星月云
 * @date 2022/10/10 20:42
 * java
 * 多线程,第3种获得多线程的方式
 */
public class CallableDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //两个线程,一个main线程,一个AAfutureTask
        //FutureTask(Callable<V> callable)
        FutureTask<Integer> futureTask =new FutureTask<>(new MyThread());
        new Thread(futureTask,"AA").start();
        new Thread(futureTask,"BB").start();//BB复用
        while (!futureTask.isDone());
        int result01=100;
        int result02=futureTask.get();//要求获得Callable线程的计算结果,如果没有计算完成就要去强求,会导致堵塞,值得计算完成
        System.out.println("****result"+(result01+result02));
    }
}

46 线程池使用及优势

为什么用线程池,优势

线程池做的工作主要是控制运行的线程的数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果线程数量超过了大数量超出数量的线程排队等候,等其它线程执行完毕,再从队列中取出任务来执行。
他的主要特点为:线程复用:控制最大并发数;管理线程

第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。

第二:提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。

第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控

47 线程池3个常用方式

线程池如何使用?

架构说明

Java中的线程池是通过Executor框架实现的,该框架中用到了Executor,Executors,ExecutorService,ThreadPoolExecutor这几个类。



编码实现

了解

Executors.newScheduledThreadPool()

java8新出——Executors.newWorkStealinPool(int)——java8新增,使用目前机器上可用的处理器作为它的并行级别

重点

Executors.newFixedThreadPool(int)

执行长期的任务,性能好很多


Executors.newSingleThreadExecutor()

一个任务一个任务执行的场景

Executors.newCachedThreadPool()

适用:执行很多短期异步的小程序或者负载较轻的服务


48 线程池7大参数入门简介

ThreadPoolExecutor



线程池的几个重要参数介绍?

七个参数



49 线程池7大参数深入介绍

1.corePoolSize:线程池中的常驻核心线程数


1在创建了线程池后,当有请求任务来之后,就会安排池中的线程去执行请求任务,近似理解为今日当值线程


2当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中;


2.maximumPoolSize:线程池能够容纳同时执行的最大线程数,此值必须大于等于1

corePoolSize和workQueue满了


3.keepAliveTime:多余的空闲线程的存活时间。

当前线程池数量超过corePoolSize时,当空闲时间达到keepAliveTime值时,

多余空闲线程会被销毁直到只剩下corePoolSize个线程为止


4.unit: keepAliveTime的单位。


5.workQueue:任务队列,被提交但尚未被执行的任务。


6.threadFactory:表示生成线程池中工作线程的线程工厂,用于创建线程一般用默认的即可。


7.handler:拒绝策略,表示当队列满了并且工作线程大于等于线程池的最大线程数(maximumPoolSize)时如何来指定


以顾客去银行办理业务为例,谈谈线程池的底层工作原理


1.最开始假设来了两个顾客,因为corePoolSize为2,因此这两个顾客直接能够去窗口办理

2.后面又来了三个顾客,因为corePool已经被顾客占用了,因此只有去候客区,也就是阻塞队列中等待

3.后面的人又陆陆续续来了,候客区可能不够用了,因此需要申请增加处理请求的窗口,这里的窗口指的是线程池中的线程数,以此来解决线程不够用的问题

4.假设受理窗口已经达到最大数,并且请求数还是不断递增,此时候客区和线程池都已经满了,为了防止大量请求冲垮线程池,已经需要开启拒绝策略

5.临时增加的线程会因为超过了最大存活时间,就会销毁,最后从最大数削减到核心数

package threadpool8;
import java.util.concurrent.*;
/**
 * @author CSDN@日星月云
 * @date 2022/10/11 19:20
 */
public class T1 {
    public static void main(String[] args) {
        ExecutorService threadPool = new ThreadPoolExecutor(
                2,
                5,
                100L, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(3),//等候区
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
        try {
            for (int i = 1; i <= 8; i++) { //模拟6个顾客来办理业务,受理窗口max只有5个
                final int tmpI = i;
                threadPool.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + "号窗口,”+“服务顾客" + tmpI);
                    try {
                        TimeUnit.SECONDS.sleep(4);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadPool.shutdown();
        }
    }
}
pool-1-thread-1号窗口,”+“服务顾客1
pool-1-thread-5号窗口,”+“服务顾客8
pool-1-thread-2号窗口,”+“服务顾客2
pool-1-thread-3号窗口,”+“服务顾客6
pool-1-thread-4号窗口,”+“服务顾客7
pool-1-thread-2号窗口,”+“服务顾客3
pool-1-thread-3号窗口,”+“服务顾客4
pool-1-thread-5号窗口,”+“服务顾客5

总结:

corePoolSize今日当值,

workQueue等候区

当今日当值与等候区满员了,就会开通所有的窗口maximumPoolSize

如果业务量仍然增多,大堂经理采取拒绝策略handler

如果业务量慢慢减少,keepAliveTime(unit)内没有增多,就会缩减窗口直到今日当值

50 线程池底层工作原理

说说线程池的底层工作原理?


在创建了线程池后,等待提交过来的任务请求

当调用execute()方法添加一个请求任务时,线程池会做出如下判断

如果正在运行的线程池数量小于corePoolSize,那么马上创建线程运行这个任务

如果正在运行的线程数量大于或等于corePoolSize,那么将这个任务放入队列

如果这时候队列满了,并且正在运行的线程数量还小于maximumPoolSize,那么还是创建非核心线程like运行这个任务;

如果队列满了并且正在运行的线程数量大于或等于maximumPoolSize,那么线程池会启动饱和拒绝策略来执行

当一个线程完成任务时,它会从队列中取下一个任务来执行

当一个线程无事可做操作一定的时间(keepAliveTime)时,线程池会判断:

如果当前运行的线程数大于corePoolSize,那么这个线程就被停掉

所以线程池的所有任务完成后,它会最终收缩到corePoolSize的大小

最后


2022 10/11 19:45


p45~p50


Markdown 4981 字数 292 行数

HTML 4221 字数 156 段落

相关文章
|
4小时前
|
存储 Java
面试官:素有Java锁王称号的‘StampedLock’你知道吗?我:这什么鬼?
面试官:素有Java锁王称号的‘StampedLock’你知道吗?我:这什么鬼?
43 23
|
4小时前
|
安全 Java 调度
深入理解Java并发编程:线程安全与性能优化
【5月更文挑战第12天】 在现代软件开发中,多线程编程是提升应用程序性能和响应能力的关键手段之一。特别是在Java语言中,由于其内置的跨平台线程支持,开发者可以轻松地创建和管理线程。然而,随之而来的并发问题也不容小觑。本文将探讨Java并发编程的核心概念,包括线程安全策略、锁机制以及性能优化技巧。通过实例分析与性能比较,我们旨在为读者提供一套既确保线程安全又兼顾性能的编程指导。
|
4小时前
|
消息中间件 安全 前端开发
字节面试:说说Java中的锁机制?
Java 中的锁(Locking)机制主要是为了解决多线程环境下,对共享资源并发访问时的同步和互斥控制,以确保共享资源的安全访问。 锁的作用主要体现在以下几个方面: 1. **互斥访问**:确保在任何时刻,只有一个线程能够访问特定的资源或执行特定的代码段。这防止了多个线程同时修改同一资源导致的数据不一致问题。 2. **内存可见性**:通过锁的获取和释放,可以确保在锁保护的代码块中对共享变量的修改对其他线程可见。这是因为 Java 内存模型(JMM)规定,对锁的释放会把修改过的共享变量从线程的工作内存刷新到主内存中,而获取锁时会从主内存中读取最新的共享变量值。 3. **保证原子性**:锁
15 1
|
4小时前
|
Java
Java中的多线程编程:基础知识与实践
【5月更文挑战第13天】在计算机科学中,多线程是一种使得程序可以同时执行多个任务的技术。在Java语言中,多线程的实现主要依赖于java.lang.Thread类和java.lang.Runnable接口。本文将深入探讨Java中的多线程编程,包括其基本概念、实现方法以及一些常见的问题和解决方案。
|
4小时前
|
安全 算法 Java
深入理解Java并发编程:线程安全与性能优化
【5月更文挑战第13天】 在Java开发中,并发编程是一个复杂且重要的领域。它不仅关系到程序的线程安全性,也直接影响到系统的性能表现。本文将探讨Java并发编程的核心概念,包括线程同步机制、锁优化技术以及如何平衡线程安全和性能。通过分析具体案例,我们将提供实用的编程技巧和最佳实践,帮助开发者在确保线程安全的同时,提升应用性能。
10 1
|
4小时前
|
Java 调度
Java一分钟之线程池:ExecutorService与Future
【5月更文挑战第12天】Java并发编程中,`ExecutorService`和`Future`是关键组件,简化多线程并提供异步执行能力。`ExecutorService`是线程池接口,用于提交任务到线程池,如`ThreadPoolExecutor`和`ScheduledThreadPoolExecutor`。通过`submit()`提交任务并返回`Future`对象,可检查任务状态、获取结果或取消任务。注意处理`ExecutionException`和避免无限等待。实战示例展示了如何异步执行任务并获取结果。理解这些概念对提升并发性能至关重要。
17 5
|
4小时前
|
Java
Java一分钟:线程协作:wait(), notify(), notifyAll()
【5月更文挑战第11天】本文介绍了Java多线程编程中的`wait()`, `notify()`, `notifyAll()`方法,它们用于线程间通信和同步。这些方法在`synchronized`代码块中使用,控制线程执行和资源访问。文章讨论了常见问题,如死锁、未捕获异常、同步使用错误及通知错误,并提供了生产者-消费者模型的示例代码,强调理解并正确使用这些方法对实现线程协作的重要性。
14 3
|
4小时前
|
安全 算法 Java
Java一分钟:线程同步:synchronized关键字
【5月更文挑战第11天】Java中的`synchronized`关键字用于线程同步,防止竞态条件,确保数据一致性。本文介绍了其工作原理、常见问题及避免策略。同步方法和同步代码块是两种使用形式,需注意避免死锁、过度使用导致的性能影响以及理解锁的可重入性和升级降级机制。示例展示了同步方法和代码块的运用,以及如何避免死锁。正确使用`synchronized`是编写多线程安全代码的核心。
56 2
|
4小时前
|
安全 Java 调度
Java一分钟:多线程编程初步:Thread类与Runnable接口
【5月更文挑战第11天】本文介绍了Java中创建线程的两种方式:继承Thread类和实现Runnable接口,并讨论了多线程编程中的常见问题,如资源浪费、线程安全、死锁和优先级问题,提出了解决策略。示例展示了线程通信的生产者-消费者模型,强调理解和掌握线程操作对编写高效并发程序的重要性。
43 3
|
4小时前
|
安全 Java
深入理解Java并发编程:线程安全与性能优化
【5月更文挑战第11天】在Java并发编程中,线程安全和性能优化是两个重要的主题。本文将深入探讨这两个方面,包括线程安全的基本概念,如何实现线程安全,以及如何在保证线程安全的同时进行性能优化。我们将通过实例和代码片段来说明这些概念和技术。
4 0