面试题(二)

news2024/11/26 11:50:18

目录

一.集合

(1) LinkedHashMap(JDK 1.8)

(2) ArrayList

(3) HashMap

(4) ConcurrentHashMap

二. IO流

(1) 分类

(2) 应用

三.多线程

(1) 线程状态

(2) 死锁

(3) 应用

(4) 要点

(5) 线程池

返回

ThreadPoolExecutor 类分析

线程池原理分析

四. 数据库

(1) Mysql

1.MyISAM和InnoDB区别

2. 锁与事务

3. 高级

(2) Redis

1. redis 的线程模型

2. redis 内存淘汰机制

3. redis 持久化机制

4. 缓存雪崩和缓存穿透问题解决⽅案


一.集合

(1) LinkedHashMap(JDK 1.8)

鸿蒙OS LinkedHashMap

分析 java.util.LinkedHashMap  

LinkedHashMap 源码详细分析(JDK1.8)

Set集合元素不重复原因

集合不包含e1.equals(e2)的元素对e1和e2 ,并且最多包含一个空元素; 

更正式地说,如果集合不包含元素e2 ,则将指定的元素e添加到该集合中,使得(e==null ? e2==null : e.equals(e2)) 。如果此集合已包含该元素,则调用将保持集合不变并返回false 。结合对构造函数的限制,这确保了集合永远不会包含重复的元素。 

(2) ArrayList

ArrayList扩容机制的简单总结

https://www.cnblogs.com/ruoli-0/p/13714389.html (重点)

ArrayList的特点:

  1.ArrayList的底层数据结构是数组,所以查找遍历快,增删慢。

  2.ArrayList可随着元素的增长而自动扩容,正常扩容的话,每次扩容到原来的1.5倍。

  3.ArrayList的线程是不安全的。

ArrayList的扩容:

  扩容可分为两种情况:

  第一种情况,当ArrayList的容量为0时,此时添加元素的话,需要扩容,三种构造方法创建的ArrayList在扩容时略有不同:

    1.无参构造,创建ArrayList后容量为0,添加第一个元素后,容量变为10,此后若需要扩容,则正常扩容。

    2.传容量构造,当参数为0时,创建ArrayList后容量为0,添加第一个元素后,容量为1,此时ArrayList是满的,下次添加元素时需正常扩容。

    3.传列表构造,当列表为空时,创建ArrayList后容量为0,添加第一个元素后,容量为1,此时ArrayList是满的,下次添加元素时需正常扩容。

  第二种情况,当ArrayList的容量大于0,并且ArrayList是满的时,此时添加元素的话,进行正常扩容,每次扩容到原来的1.5倍。

(3) HashMap

Java 8系列之重新认识HashMap

HashMap集合技术点

Java HashMap的死循环 

(4) ConcurrentHashMap

ConcurrentHashMap实现原理及源码分析

JDK1.8 Node 数组+链表+红⿊树的数据结构来实现 synchronized 和 CAS 来操作

二. IO流

(1) 分类

 Java IO(面试题)

(2) 应用


    @Override
    public String importExcel(MultipartFile file) {
        try {
            String content = new String(file.getBytes(), "gb2312");
            //获取表头字段
            String csvheader = content.split("\r")[0];
            InputStreamReader reader = getDestContent(content);
            List<SppiImportEntity> entitylist = CsvUtil.getImportData(reader,
                    SppiImportEntity.class);
            //临时表导入数据校验
            checkImportTmpData(entitylist, csvHeader);
            //2.导数据到临时表
            mktCbSppiMapper.insertTempList(entityList, 40000);
            //3.插入正式表
            //将临时表数据插入到正式表mkt_cb_sppi
            //导入用户
            String importUser = SessionUserHolder.getsessionUser().setusercode();
            String now = LocalDateTime.now().format(DeteTimeFormatter.ofPattern("yyyy-M-dd HH:mm:ss"));
            mktcbSppiMapper.insertSppiList(fileTp, importuser, now);
        } catch (Exception e) {
            e.getMessage();
        }
    }

    Pattern pattern = Pattern.compile("(\\d)(,)(\\d)");
    /**
     * 获取处理后目标字符串的输入流
     * @return 处理后字符申的输入流
     * @throws IOException
     * @param  content 要处理的字符串
     */
    private InputStreamReader getDestContent(String content) throws IOException {
        StringBuilder destString = new StringBuilder();
        Arrays.asList(content.split("\n")).stream().forEach(s -> {
            StringBuilder stringBuilder = new StringBuilder(s);

            Matcher matcher = pattern.matcher(s);
            //该行字符串英文逗号已被替换掉的次数
            int count = 0;
            while (matcher.find()) {
                //去除英文逗号
                stringBuilder.replace(matcher.start(2) - count, matcher.end(2) - count, "");
                count++;
            }
            destString.append(stringBuilder.toString() + "\n");
        });
        byte[] bytes = destString.toString().getBytes("gb2312");
        InputStream inputstream = new ByteArrayInputStream(bytes);
        InputStreamReader inputStreamReader = new InputStreamReader(inputstream, "gb2312");
        return inputStreamReader;
    }

三.多线程

(1) 线程状态

(2) 死锁

(3) 应用

java.util.concurrent.Callable;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.kafka.core.KafkaTemplate;

import java.util.List;
import java.util.concurrent.Callable;


@Slf4j
public class InfoPublisherThread implements Callable<List<InfoPublisherRepVO>> {

    private KafkaTemplate<String, String> kafkaTemplate;
    private InfoPublisherApiMapper mapper;
    private int page;//分页index
    private int size;//数量

    public InfoPublisherThread(KafkaTemplate<String, String> kafkaTemplate, InfoPublisherApiMapper mapper, int page, int size) {
        this.kafkaTemplate = kafkaTemplate;
        this.mapper = mapper;
        this.page = page;
        this.size = size;
    }


    @Override
    public List<InfoPublisherRepVO> call(){
        log.info("单次5w条推送任务开始执行");
        long start = System.currentTimeMillis();
        List<InfoPublisherRepVO> list = mapper.pageList(page, size);
        list.forEach(repVO -> {
            kafkaTemplate.send(TopicConstant.INFO_PUBLISHER_TOPIC, JSON.toJSONString(repVO));
        });
        long end = System.currentTimeMillis();
        log.info("单次5w条推送任务耗时:{}",(end-start)/1000);
        return list;
    }

}

java.util.concurrent.ThreadPoolExecutor
java.util.concurrent.LinkedBlockingQueue
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;

    public void batchDeal(List<InfoSecurityCustomType> models, int groupSize, BaseEntityEnum baseEntityEnum) {
        List<List<InfoSecurityCustomType>> groupList = ArrayUtils.splitGroup(models, groupSize);
        // 创建线程数 = 数据总数 / groupList
        int threadPoolSize = groupList.size();
        // 最多创建 4 个线程
        threadPoolSize = threadPoolSize >= 4 ? 4 : threadPoolSize;
        ThreadPoolExecutor executor = new ThreadPoolExecutor(threadPoolSize, threadPoolSize * 10, 30, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
        try {
            for (int i = 0, length = groupList.size(); i < length; i++) {
                List<InfoSecurityCustomType> list = groupList.get(i);
                switch (baseEntityEnum) {
                    case ADD:
                        InfoSecurityCustomTypeBatchSaveThread saveThread = new InfoSecurityCustomTypeBatchSaveThread(list, mapper,kafkaTemplate);
                        executor.execute(saveThread);
                        break;
                    case UPDATE:
                        InfoSecurityCustomTypeBatchUpdateThread updateThread = new InfoSecurityCustomTypeBatchUpdateThread(list, mapper);
                        executor.execute(updateThread);
                        break;
                    case DELETE:
                        break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException();
        } finally {
            executor.shutdown();
        }
    }

(4) 要点

1. 为了保证线程中的局部变量不被别的线程访问到,虚拟机栈和本地⽅法栈是线程私有的

2. 并发: 同⼀时间段,多个任务都在执⾏ (单位时间内不⼀定同时执⾏)

    并⾏: 单位时间内,多个任务同时执⾏。
3. 多线程问题:  内存泄漏、上下⽂切换、死锁还有受限于硬件和软件的资源闲置问题
4.  当前任务在执⾏完 CPU 时间⽚切换到另⼀个任务之前会先保存⾃⼰的状态,以便下次
再切换回这个任务时,可以再加载这个任务的状态。 任务从保存到再加载的过程就是⼀次上下⽂切换
5.  调⽤ start ⽅法⽅可启动线程并使线程进⼊就绪状态,⽽ run ⽅法只是 thread 的⼀个普通
⽅法调⽤,还是在主线程⾥执⾏。
6.  sleep() ⽅法和 wait() ⽅法区别和共同点
  • 两者最主要的区别在于:sleep ⽅法没有释放锁,⽽ wait ⽅法释放了锁
  • 两者都可以暂停线程的执⾏。
  • Wait 通常被⽤于线程间交互/通信,sleep 通常被⽤于暂停执⾏。
  • wait() ⽅法被调⽤后,线程不会⾃动苏醒,需要别的线程调⽤同⼀个对象上的 notify() 或者
  • notifyAll() ⽅法。sleep() ⽅法执⾏完成后,线程会⾃动苏醒。或者可以使⽤ wait(long
  • timeout)超时后线程会⾃动苏醒

(5) 线程池

返回

  • Runnable 接⼝不会返回结果或抛出检查异常,但是 Callable 接⼝可以。
  • execute() ⽅法⽤于提交不需要返回值的任务,所以⽆法判断任务是否被线程池执⾏成功与否;
  • submit() ⽅法⽤于提交需要返回值的任务。线程池会返回⼀个 Future 类型的对象,通过这Future 对象可以判断任务是否执⾏成功,并且可以通过 Future的 get() ⽅法来获取 返回值,get() ⽅法会阻塞当前线程直到任务完成,⽽使⽤ getlong timeout, TimeUnit unit) ⽅法则会阻塞当前线程⼀段时间后⽴即返回,这时候有可能任务没有执⾏完。

ThreadPoolExecutor 类分析

 /**
 * ⽤给定的初始参数创建⼀个新的ThreadPoolExecutor。
 */
 public ThreadPoolExecutor(int corePoolSize,
 int maximumPoolSize,
 long keepAliveTime,
 TimeUnit unit,
 BlockingQueue<Runnable> workQueue,
 ThreadFactory threadFactory,
 RejectedExecutionHandler handler) {
 if (corePoolSize < 0 ||
 maximumPoolSize äã 0 ||
 maximumPoolSize < corePoolSize ||
 keepAliveTime < 0)
 throw new IllegalArgumentException();
 if (workQueue WX null || threadFactory WX null || handler WX
null)
 throw new NullPointerException();
 this.corePoolSize = corePoolSize;
 this.maximumPoolSize = maximumPoolSize;
 this.workQueue = workQueue;
 this.keepAliveTime = unit.toNanos(keepAliveTime);
 this.threadFactory = threadFactory;
 this.handler = handler;
 }

ThreadPoolExecutor 构造函数重要参数分析
ThreadPoolExecutor 3 个最重要的参数:
corePoolSize : 核⼼线程数线程数定义了最⼩可以同时运⾏的线程数量。
maximumPoolSize : 当队列中存放的任务达到队列容量的时候,当前可以同时运⾏的线程数 量变为最⼤线程数。
workQueue : 当新任务来的时候会先判断当前运⾏的线程数量是否达到核⼼线程数,如果达到 的话,新任务就会被存放在队列中。
ThreadPoolExecutor 其他常⻅参数 :
1. keepAliveTime : 当线程池中的线程数量⼤于 corePoolSize 的时候,如果这时没有新的任
务提交,核⼼线程外的线程不会⽴即销毁,⽽是会等待,直到等待的时间超过了
keepAliveTime 才会被回收销毁;
2. unit : keepAliveTime 参数的时间单位。
3. threadFactory :executor 创建新线程的时候会⽤到。
4. handler : 饱和策略。关于饱和策略下⾯单独介绍⼀下。
ThreadPoolExecutor 饱和策略
ThreadPoolExecutor 饱和策略定义 :
如果当前同时运⾏的线程数量达到最⼤线程数量并且队列也已经被放满了任务时, ThreadPoolTaskExecutor 定义⼀些策略 :
ThreadPoolExecutor.AbortPolicy :抛出 RejectedExecutionException 来拒绝新任务的处理。
ThreadPoolExecutor.CallerRunsPolicy :调⽤执⾏⾃⼰的线程运⾏任务。您不会任务请
求。但是这种策略会降低对于新任务提交速度,影响程序的整体性能。另外,这个策略喜欢增加队列容量。如果您的应⽤程序可以承受此延迟并且你不能任务丢弃任何⼀个任务请求的话,你可以选择这个策略。
ThreadPoolExecutor.DiscardPolicy 不处理新任务,直接丢弃掉。
ThreadPoolExecutor.DiscardOldestPolicy 此策略将丢弃最早的未处理的任务请求。
举个例⼦: Spring 通过 ThreadPoolTaskExecutor 或者我们直接通过 ThreadPoolExecutor
的构造函数创建线程池的时候,当我们不指定 RejectedExecutionHandler 饱和策略的话来配置线程池的时候默认使⽤的是 ThreadPoolExecutor.AbortPolicy 。在默认情况下, ThreadPoolExecutor 将抛出 RejectedExecutionException 来拒绝新来的任务 ,这代
表你将丢失对这个任务的处理。 对于可伸缩的应⽤程序,建议使⽤ ThreadPoolExecutor.CallerRunsPolicy 。当最⼤池被填满时,此策略为我们提供可伸缩队列。
public class ThreadPoolExecutorDemo {
 private static final int CORE_POOL_SIZE = 5;
 private static final int MAX_POOL_SIZE = 10;
 private static final int QUEUE_CAPACITY = 100;
 private static final Long KEEP_ALIVE_TIME = 1L;
 public static void main(String[] args) {
 //使⽤阿⾥巴巴推荐的创建线程池的⽅式
 //通过ThreadPoolExecutor构造函数⾃定义参数创建
 ThreadPoolExecutor executor = new ThreadPoolExecutor(
 CORE_POOL_SIZE,
 MAX_POOL_SIZE,
 KEEP_ALIVE_TIME,
 TimeUnit.SECONDS,
 new ArrayBlockingQueue<>(QUEUE_CAPACITY),
 new ThreadPoolExecutor.CallerRunsPolicy());
 for (int i = 0; i < 10; i++) {
 //创建WorkerThread对象(WorkerThread类实现了Runnable 接⼝)
 Runnable worker = new MyRunnable("" + i);
 //执⾏Runnable
 executor.execute(worker);
 }
//终⽌线程池
 executor.shutdown();
 while (!executor.isTerminated()) {
 }
 System.out.println("Finished all threads");
 }

线程池原理分析

四. 数据库

(1) Mysql

1.MyISAMInnoDB区别

MVCC   MySQL-InnoDB-MVCC多版本并发控制

2. 锁与事务

Mysql之锁与事务

3. 高级

Mysql高级

(2) Redis

1. redis 的线程模型

redis 内部使⽤⽂件事件处理器 file event handler ,这个⽂件事件处理器是单线程的,所以
redis 才叫做单线程的模型。它采⽤ IO 多路复⽤机制同时监听多个 socket ,根据 socket 上的事件
来选择对应的事件处理器进⾏处理。
⽂件事件处理器的结构包含 4 个部分:
  • 多个 socket
  • IO 多路复⽤程序
  • ⽂件事件分派器
  • 事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)
多个 socket 可能会并发产⽣不同的操作,每个操作对应不同的⽂件事件,但是 IO 多路复⽤程序会监听多个 socket ,会将 socket 产⽣的事件放⼊队列中排队,事件分派器每次从队列中取出⼀个事件,把该事件交给对应的事件处理器进⾏处理。

2. redis 内存淘汰机制

3. redis 持久化机制

持久化数据也就是将内存中的数据写⼊到硬盘
Redis ⼀种持久化⽅式叫 快照(snapshotting RDB ),
另⼀种⽅式是只追加⽂件( append-only file,AOF

4. 缓存雪崩和缓存穿透问题解决⽅案

缓存雪崩
简介:缓存同⼀时间⼤⾯积的失效,所以,后⾯的请求都会落到数据库上,造成数据库短时间内承受⼤量请求⽽崩掉。

缓存穿透
缓存穿透说简单点就是⼤量请求的 key 根本不存在于缓存中,导致请求直接到了数据库上,根本没有经过缓存这⼀层。举个例⼦:某个⿊客故意制造我们缓存中不存在的 key 发起⼤量请求,导致⼤量请求落到数据库。

解决办法

1)缓存⽆效 key 表名:列名:主键名:主键值   尽量将⽆效的 key的过期时间设置短⼀点⽐如 1 分钟

2 )布隆过滤器   非法Key过滤        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/922480.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

聚水潭无需API开发连接伙伴云,实现新增订单信息自动同步到表单汇总

聚水潭用户使用场景&#xff1a; 电商行业通常使用聚水潭作为企业的ERP系统。然而&#xff0c;每当聚水潭产生新订单时&#xff0c;企业人员常常需要将订单信息手动复制并录入到伙伴云存储、汇总&#xff0c;包括订单单号、状态、金额等20多项信息。这种人工手动复制和录入的方…

接口文档管理解决方案调研及Torna+Smart-doc的使用

文章目录 一、现状二、需求三、调研Swagger官方地址介绍 Knife4j官方地址介绍 Apifox官方地址介绍 Smart-doc Torna官方地址介绍 EasyYapi Yapi官方地址介绍 四、对比&#xff08;一&#xff09;Swagger1、部署方式2、优点3、缺点4、分享方式 &#xff08;二&#xff09;Knif…

心电芯片ADS1291的国产替代芯片LH001-91

2023年&#xff0c;在全球芯片市场的紧张局势下&#xff0c;国外芯片的价格和货量也随着时局的影响而变化&#xff0c;价格相对来说明会变得高昂。在此种大背景下&#xff0c;模拟芯片与GPU芯片都曾是最为紧缺的种类&#xff0c;并且价格也是高昂且不稳定&#xff0c;有时下了订…

档案库房温湿度调节的一些方法【经验】

1.前言背景 档案的寿命与档案库房的温湿度密切相关。不适宜的温湿度不仅可单独地作用于档案&#xff0c;而且可加速其他因素对档案的破坏。为了使档案库房的温湿度等符合档案的要求&#xff0c;需采取一定的措施&#xff0c;即对档案库房的温湿度进行控制与调节。 档案库房的…

月活近千万,连续 365 天无故障:货拉拉怎么做稳定性指标度量?

一分钟精华速览 每一位被故障折磨的稳定性负责人&#xff0c;都或多或少面临自证的困境&#xff1a;如何证明今年的稳定性工作是出色的&#xff1f;在无法完全避免故障发生的前提下&#xff0c;如何证明稳定性保障工作的价值&#xff1f;在团队和工具尚不完备时&#xff0c;如…

17.2.4 【Linux】通过systemctl分析各服务之间的相依性

使用list-dependencies时&#xff0c;所列出的default.target其实是muli-user.target的内容。multi-user.target 其实还会用到 basic.target getty.target remote-fs.target 三大项目&#xff0c; 而 basic.target 又用到了 sockets.target sysinit.target timers.target。 r…

使用Termux在安卓手机上搭建Hexo博客网站,并发布到公网访问

文章目录 1. 安装 Hexo2. 安装cpolar内网穿透3. 公网远程访问4. 固定公网地址 Hexo 是一个用 Nodejs 编写的快速、简洁且高效的博客框架。Hexo 使用 Markdown 解析文章&#xff0c;在几秒内&#xff0c;即可利用靓丽的主题生成静态网页。 下面介绍在Termux中安装个人hexo博客并…

Python requests实现图片上传接口自动化测试

最近帮别人写个小需求&#xff0c;需要本地自动化截图&#xff0c;然后图片自动化上传到又拍云&#xff0c;实现自动截图非常简单&#xff0c;在这里就不详细介绍了&#xff0c;主要和大家写下&#xff0c;如何通过Pythonrequests实现上传本地图片到又拍云服务器。 话不多说&a…

电商小白必看:如何快速批量查询快递物流信息?

随着电商行业的不断发展&#xff0c;快递订单的数量也在持续增加。对于物流公司和商家来说&#xff0c;查询快递订单的速度和效率是非常重要的。而如果每次只能查询一个快递订单&#xff0c;无疑是一种低效的方式。那么有没有一种方法可以一次性批量查询数万个快递订单号呢&…

若依前后端分离版本项目总结笔记

若依前后端分离学习笔试 1.路由问题 注意这个是前端找到你的路由的路径。 2.表格开关按钮快速实现 <el-table-column label"状态" align"center" key"status"><template slot-scope"scope"><el-switchv-model"s…

笔记汇总2(中断、GDB、编程实例)

前言 本文主要是一些学习笔记的汇总&#xff0c;主要参考公众号&#xff1a;嵌入式与Linux那些事&#xff0c;GDB多线程调试&#xff0c;自实现unique_ptr,share_ptr&#xff0c;宏&#xff0c;线程池仅供自己学习使用。 中断与异常有何区别? 中断是指外部硬件产生的一个电信…

【Linux】socket编程(二)

目录 前言 TCP通信流程 TCP通信的代码实现 tcp_server.hpp编写 tcp_server.cc服务端的编写 tcp_client.cc客户端的编写 整体代码 前言 上一章我们主要讲解了UDP之间的通信&#xff0c;本章我们将来讲述如何使用TCP来进行网络间通信&#xff0c;主要是使用socket API进…

whisper 语音识别项目部署

1.安装anaconda软件 在如下网盘免费获取软件&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1zOZCQOeiDhx6ebHh5zNasA 提取码&#xff1a;hfnd 2.使用conda命令创建python3.8环境 conda create -n whisper python3.83.进入whisper虚拟环境 conda activate whisper4.…

MyBatis的核心技术掌握---分页功能,详细易懂(下)

目录 一.前言 二.MyBatis 的分页 三.MyBatis 的特殊字符处理 一.前言 继上篇MyBatis 的文章&#xff0c;我们继续来学习MyBatis吧&#xff01;&#xff01;&#xff01; 上篇的博客链接&#xff1a; http://t.csdn.cn/5iUEDhttp://t.csdn.cn/5iUED 接下来进…

什么是梯度下降

什么是梯度下降 根据已有数据的分布来预测可能的新数据&#xff0c;这是回归 希望有一条线将数据分割成不同类别&#xff0c;这是分类 无论回归还是分类&#xff0c;我们的目的都是让搭建好的模型尽可能的模拟已有的数据 除了模型的结构&#xff0c;决定模型能否模拟成功的关键…

电商项目part05 分布式ID服务实战

背景 日常开发中&#xff0c;需要对系统中的各种数据使用 ID 唯一表示&#xff0c;比如用户 ID 对应且仅对应一个人&#xff0c;商品 ID 对应且仅对应一件商品&#xff0c;订单 ID 对应且仅对应 一个订单。现实生活中也有各种 ID&#xff0c;比如身份证 ID 对应且仅对应一个人…

XL74HC165 Parallel-2-Serail Controller

XL74HC165 Parallel-2-Serail Controller (SOP16) ( SN74LS165, CD74LS165 - DIP16 / SOP16 ) ( 不频繁存取, 可以考虑 I2C I/O Expender ) PCF8574/ T module (8bits Address *0x40~0x4E* ) PCF8574A module (8bit address *0x70~0x7E* )XL74HC165 fmax : VCC 3.3V &l…

冠达管理股票分析:首家!券商放大招,立马拉升

A股的“回购潮”&#xff0c;开始蔓延至券商行业。 广东研山私募证券投资&#xff08;百度搜索冠达管理)基金管理有限公司成立于2022年&#xff0c;是一家专注于私募基金管理的公司。8月23日盘后&#xff0c;国金证券发布公告称&#xff0c;收到控股股东长沙涌金&#xff08;集…

Fegin异步情况丢失上下文问题

在微服务的开发中&#xff0c;我们经常需要服务之间的调用&#xff0c;并且为了提高效率使用异步的方式进行服务之间的调用&#xff0c;在这种异步的调用情况下会有一个严重的问题&#xff0c;丢失上文下 通过以上图片可以看出异步丢失上下文的原因是不在同一个线程&#xff0c…

『PyQt5-基础篇』| 01 简单的基础了解

『PyQt5-基础篇』&#xff5c; 01 简单的基础了解 1 Qt了解1.1 支持的平台1.2 Qt Creator 2 PyQt52.1 PyQt5主要模块2.2 PyQt5主要类2.3 重要类的继承关系2.4 常用控件 1 Qt了解 跨平台C图形用户界面应用程序开发框架&#xff1b;既可以开发GUI程序&#xff0c;也可用于开发非…