Java面试宝典-并发编程学习01

news2024/11/25 2:30:28

Java 并发编程学习

1、创建线程的有哪些方式?

创建线程的方式有以下几种:

1. 继承Thread类:创建一个类继承Thread类,并重写run()方法,然后通过创建类的实例来创建线程。

2. 实现Runnable接口:创建一个类实现Runnable接口,并重写run()方法,然后通过创建Runnable对象来创建线程。

3. 使用Executor框架:通过Executor框架创建线程,可以使用线程池来管理和调度线程的执行。

4. 使用Callable和Future:使用Callable接口可以在执行完任务后返回结果,使用Future接口可以获取Callable执行的结果。

5. 使用定时器:使用Timer类可以在指定时间间隔执行任务。

6. 使用线程池:可以使用线程池来管理和调度线程的执行,可以通过ThreadPoolExecutor类或Executors工具类来创建线程池。

这些方式各有优缺点,选择合适的方式取决于具体的需求和场景。

2、创建线程的常用的三种方式如何选择?

(1)继承Thread类 创建简单,但Java不支持多重继承,如果已经继承了其他类,就无法再继承Thread类。

(2)实现Runnable接口 可以避免单一继承的局限性,因为一个类可以实现多个接口。

(3)通过Callable和Future创建线程 Callable接口有返回值,并且能够抛出异常。 提供了更强大的异步执行机制,能够获得任务执行的结果或取消任务。

因此,如果只是创建简单的线程,可以选择继承Thread类;如果需要实现多接口或者避免单一继承的限制,可以选择实现Runnable接口; 如果需要更复杂的异步执行和结果获取,可以选择实现Callable接口配合FutureTask。

3、线程的run()start()有什么区别?

线程的run()方法和start()方法的区别如下:

1. run()方法是线程的主体,包含了线程要执行的代码;而start()方法用于启动线程,创建一个新的线程并使其进入就绪状态,等待系统调度并执行run()方法。

2. 直接调用run()方法会在当前线程中执行普通的方法调用,没有创建新的线程,只是按照顺序执行方法中的代码。而调用start()方法会创建一个新的线程,并在新线程中执行run()方法中的代码。

3. 注意:不应该直接调用run()方法来启动线程。应该通过调用start()方法来启动线程,以便系统能够正确地管理线程的生命周期和资源分配。

4、为什么我们调用 start() 方法时会执行 run() 方法,为什么我们不能直接调用 run() 法?

在Java中,Thread类中的start()方法用于启动一个新的线程,并在新线程中调用run()方法。而直接调用run()方法只是普通的方法调用,不会创建新的线程。

当调用start()方法时,实际上会完成以下几个步骤:

1. 创建一个新的线程。

2. 调用新线程的run()方法。

而直接调用run()方法只会执行该方法,不会创建新的线程。这样的话,多线程的特性就无法体现出来,只是单纯的顺序执行方法而已。

所以,如果我们希望实现多线程的效果,就应该调用start()方法,让系统自动创建新的线程并调用run()方法。而直接调用run()方法只会在当前线程中顺序执行该方法的代码,不会创建新的线程。

5servlet是线程安全的吗?

Servlet是线程安全的。Servlet容器在每个请求到达时会创建一个新的线程来处理请求。这意味着每个请求都会有自己的线程来执行,避免了多个请求之间的线程安全问题。但是需要注意的是,Servlet中的成员变量(即类级变量)是共享的,在多线程环境下需要注意对共享数据的访问控制,可以使用synchronized关键字或其他线程同步机制来确保线程安全。

可以采用哪些措施保证servlet的线程安全呢?

① 不在Servlet中使用实例变量来存储状态信息,可以使用局部变量来代替,因为局部变量存储在每个线程自己的栈中,自然是线程安全的。

② 如果必须使用实例变量,可以通过同步机制(如synchronized关键字)来确保同一时间只有一个线程能够访问和修改这些变量。

③ 对于每个线程需要独立存储的数据,可以使用ThreadLocal类来实现线程局部存储,这样每个线程都有自己的数据副本,互不干扰。

6、进程与线程有什么区别?

进程和线程是计算机中两个重要的执行单元,有以下区别:

1. 进程是指正在运行中的程序,它是操作系统进行资源分配和调度的基本单位。每个进程都拥有独立的地址空间、文件描述符、堆栈和其他系统资源。一个程序可以包含多个进程,这些进程可以并发执行。

2. 线程是进程中的一个执行单元,是程序执行的最小单位。一个进程可以拥有多个线程,这些线程共享该进程的地址空间和其他系统资源,但每个线程有自己的堆栈和局部变量。多线程可以实现并发执行,提高程序的响应速度和资源利用率。

3. 进程之间是独立的,它们之间互相隔离,通信需要通过进程间通信(IPC)机制。线程之间是共享资源的,它们可以直接相互通信。

4. 创建和销毁进程的开销较大,而创建和销毁线程的开销较小。线程的切换速度较快,因为它们共享了大部分的资源和上下文。

5. 由于线程共享地址空间,所以线程之间的同步和通信相对容易。而进程之间的通信要复杂一些,需要使用特殊的机制。

总的来说,进程和线程都是用于执行程序的,但进程是资源分配的基本单位,而线程是操作系统调度的基本单位。进程之间是独立的,线程之间是共享资源的。

7、什么是java线程池?

Java线程池是一种多线程处理形式,它维护着多个线程,这些线程等待监督管理者分配可并发执行的任务。线程池避免了在处理短时间任务时创建与销毁线程的代价,不仅能够保证内核的充分利用,还能防止过分调度

线程池的工作原理是:当有任务到来时,线程池从池中取出一个线程去执行该任务,任务执行结束后,线程被放回池中以备循环使用。这种模式减少了线程创建和销毁的开销,提高了系统的效率和性能

8、创建线程池的几个核心构造参数

Java中,可以使用Executors工具类来创建不同类型的线程池。线程池的核心构造参数包括:

  1. corePoolSize:线程池中的常驻核心线程数。
  2. maximumPoolSize:线程池允许的最大线程数。
  3. keepAliveTime:非核心线程空闲后的存活时间。
  4. unitkeepAliveTime的时间单位。
  5. workQueue:用来保存等待执行任务的队列。
  6. threadFactory:创建线程的工厂。
  7. handler:拒绝策略。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

    public class ThreadPoolExample {
        public static void main(String[] args) {
            // 创建固定大小的线程池
            ExecutorService executorService = Executors.newFixedThreadPool(5);

            // 创建单线程化的线程池
            ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

            // 创建固定大小的线程池,且支持定时及周期性任务
            ExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);

            // 创建自适应大小的线程池
            ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

            // 自定义线程池
            ExecutorService customThreadPool = new ThreadPoolExecutor(
                    5, // corePoolSize
                    10, // maximumPoolSize
                    1, // keepAliveTime
                    TimeUnit.MINUTES, // unit
                    new ArrayBlockingQueue<>(10), // workQueue
                    Executors.defaultThreadFactory(), // threadFactory
                    new ThreadPoolExecutor.AbortPolicy() // handler
            );

            // 关闭线程池
            executorService.shutdown();
            singleThreadExecutor.shutdown();
            scheduledExecutorService.shutdown();
            cachedThreadPool.shutdown();
            customThreadPool.shutdown();
        }
    }

9、线程池的类型都有什么?

Java中通过Executors类提供了四种常见的线程池类型,分别是:newSingleThreadExecutornewFixedThreadPoolnewScheduledThreadPoolnewCachedThreadPool

  1. newSingleThreadExecutor:创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序执行。这种线程池适用于需要顺序执行任务的场景,例如文件I/O操作。
  2. newFixedThreadPool:创建一个定长线程池,可控制线程的最大并发数。超出的线程会在队列中等待。这种线程池适用于需要固定数量线程的任务处理,如Web服务器。
  3. newScheduledThreadPool:创建一个可定期或者延时执行任务的定长线程池,支持定时及周期性任务执行。这种线程池适用于需要定时执行任务的场景,如定时清理缓存或定时执行某些周期性任务。
  4. newCachedThreadPool:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。这种线程池适用于执行大量短期异步任务的场景,能够动态地调整线程数量,减少资源浪费。

10、为何阿里巴巴开发手册中不允许使用Executors创建线程池?

阿里巴巴开发手册中不允许使用Executors创建线程池的主要原因是由于其可能导致资源耗尽、线程数不可控和缺乏灵活性。使用Executors创建线程池隐藏了关键配置参数,限制了开发者对线程池行为的精确控制和优化,可能导致资源使用不当或性能问题。此外,Executors提供的便捷方法通常会使用无界队列,如果任务提交速度超过处理速度,可能会导致内存溢出(OOM)的风险

具体原因包括

  1. 资源耗尽风险Executors类创建的线程池,如FixedThreadPoolSingleThreadPool,可能会导致请求队列堆积大量任务,最终引发内存溢出(OOM)的风险。特别是CachedThreadPool会无限创建新线程,直到达到系统资源的极限,这可能导致系统负载过高
  2. 不可控制的线程数Executors类创建的线程池通常具有固定的参数配置,这限制了对于线程池参数的自定义调整,如核心线程数、最大线程数、任务队列等。这可能导致系统资源被迅速耗尽
  3. 缺乏灵活性Executors类提供的线程池通常具有固定的参数配置,这限制了对于线程池参数的自定义调整,如核心线程数、最大线程数、任务队列等。这不利于根据实际需求进行细致的配置和调整
  4. 不够透明:使用Executors类创建的线程池可能不够透明,无法清晰地了解其内部工作机制和潜在问题,这对于性能调优和故障排查都是不利的

推荐的替代方案是使用ThreadPoolExecutor进行手动创建。通过直接使用ThreadPoolExecutor来创建线程池,可以让开发者更精细地控制线程池的行为,包括设置合理的线程数量、任务队列长度、拒绝策略等,从而更好地管理系统资源,避免不必要的风险。此外,推荐使用有界队列来控制线程池的任务排队数量,以避免潜在的问题

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

线程池中的线程并不是一开始就随着线程池的启动创建好的。线程池中的线程是在有任务提交时动态创建的。当一个新的任务提交到线程池时,线程池会根据当前的状态和配置来决定是否创建新线程

当一个新的任务提交到线程池时,线程池会按照以下步骤执行:

  1. 如果线程池中的线程数小于corePoolSize,则创建一个新的线程,并将任务交给这个线程执行。
  2. 如果线程池中的线程数已经等于corePoolSize,新的任务会被放入工作队列中。
  3. 如果工作队列已满,则会创建新的线程来执行任务,直到线程数达到maximumPoolSize为止。
  4. 如果线程数已经达到maximumPoolSize并且工作队列已满,则执行拒绝策略,如抛出异常或者丢弃任务

此外,如果在线程池启动时设置了prestartAllCoreThreadstrue,则会预先创建corePoolSize个线程并启动它们,这样可以提前消耗一部分资源,但仍然需要根据任务的提交情况动态地创建线程来执行任务

12、线程池的执行过程是什么?

线程池的执行过程可以分为以下几个主要步骤

  1. 提交任务:当一个新的线程任务被提交到线程池时,线程池会首先检查是否有空闲线程。如果有,则分配一个空闲线程执行该任务;如果没有空闲线程,则进行下一步判断
  2. 核心线程判断:如果当前运行的线程数小于核心线程数corePoolSize),线程池会创建一个新的核心线程来执行任务。如果当前运行的线程数已经达到或超过核心线程数,则进行下一步判断
  3. 工作队列判断:如果当前运行的线程数已经达到核心线程数,线程池会检查工作队列是否已满。如果工作队列未满,任务会被放入队列中等待执行;如果工作队列已满,则进行下一步判断
  4. 非核心线程判断:如果工作队列已满,线程池会判断当前线程数是否已达到最大线程数maximumPoolSize)。如果没有达到最大线程数,线程池会创建一个新的非核心线程来执行任务;如果已达到最大线程数,则执行拒绝策略
  5. 拒绝策略:如果所有线程都在运行且工作队列已满,且线程数已达到最大线程数,线程池会执行拒绝策略(如AbortPolicyCallerRunsPolicy等),具体策略取决于线程池的配置

13Java 线程池中 submit() execute()方法有什么区别?

Java线程池中的submit()execute()方法主要有以下区别

  1. 返回值
    • submit()方法可以接受CallableRunnable类型的任务,并返回一个Future对象。通过这个Future对象,可以获取任务的执行结果或者取消任务执行
    • execute()方法只能接受Runnable类型的任务,并且没有返回值。它直接在调用时执行任务,不会返回任何结果或Future对象
  2. 异常处理
    • submit()方法可以捕获任务执行过程中抛出的异常,并通过Future对象的get()方法重新抛出这些异常。这意味着异常可以通过编程方式处理,而不是直接暴露给调用者
    • execute()方法无法直接捕获任务执行中的异常,需要在任务内部进行异常处理。如果任务抛出未检查异常,这些异常可能会导致线程池中的线程被异常终止,从而影响线程池的稳定性
  3. 方法来源和灵活性
    • execute()方法是Executor接口中定义的方法,主要用于执行不带返回值的任务。它定义较为简单,适用于只需要执行任务而不需要结果反馈的场景
    • submit()方法是ExecutorService接口中定义的方法,在Executor的基础上增加了任务提交后可以获取任务执行结果的能力。这使得submit()方法更加灵活,适用于需要处理带返回值任务的场景

14、如果你提交任务时,线程池队列已满,这时会发生什么

当你提交任务时,如果线程池队列已满,会发生拒绝策略。

具体来说,线程池会根据其配置的拒绝策略来处理无法执行的新任务。主要有以下几种情况:

  1. 使用无界队列(如LinkedBlockingQueue:如果线程池使用的是无界队列,任务会继续添加到阻塞队列中等待执行,因为无界队列可以无限存放任务
  2. 使用有界队列(如ArrayBlockingQueue:如果线程池使用的是有界队列,当队列满时,会根据maximumPoolSize的值增加线程数量。如果增加了线程数量还是处理不过来,队列继续满,则会使用拒绝策略处理新的任务,默认是AbortPolicy‌

拒绝策略主要有以下几种:

  • AbortPolicy:直接抛出RejectedExecutionException异常。
  • CallerRunsPolicy:不在新线程中执行任务,而是在调用者的线程中直接执行任务。
  • DiscardPolicy:默默丢弃无法处理的任务,不抛出异常。
  • DiscardOldestPolicy:丢弃队列最老的任一个任务,并执行当前任务

15、说说你对核心线程数的理解?

配置文件中的线程池核心线程数为何配置为

// 获取CPU的处理器数量

int curSystemThreads = Runtime.getRuntime().availableProcessors() * 2

Runtime.getRuntime().availableProcessors()获取的是CPU核心线程数,也就是计算资源。

CPU密集型,线程池大小设置为N,也就是和cpu的线程数相同,可以尽可能地避免线程间上下文切换,但在实际开发中,一般会设置为N+1,为了防止意外情况出现线程阻塞,如果出现阻塞,多出来的线程会继续执行任务,保证CPU的利用效率。

IO密集型,线程池大小设置为2N,这个数是根据业务压测出来的,如果不涉及业务就使用推荐。

在实际中,需要对具体的线程池大小进行调整,可以通过压测及机器设备现状,进行调整大小。

如果线程池太大,则会造成CPU不断的切换,对整个系统性能也不会有太大的提升,反而会导致系统缓慢。

16、什么是线程组?

线程组在Java中主要用于方便地管理线程,它可以包含多个线程,将它们组织成一个单元,从而更容易进行管理和控制。

在Java中创建线程组时,可以使用ThreadGroup类的构造函数,可以指定线程组的名称和父线程组。默认情况下,所有的线程都属于主线程组。我们可以通过线程对象获取它所属的线程组,也可以通过线程组对象获取它所在组的名字。

线程组可以为其中的所有线程设置共同的属性,如线程优先级、是否守护线程等。

一旦线程加入某个线程组,它将一直属于该线程组,直到线程终止,且不能中途改变所属的线程组。

线程组更多地用于对线程进行分组管理和属性设置,而线程池则专注于提高系统性能,通过重用线程来减少资源消耗,并控制并发。

17、为什么在 Java 中不推荐使用线程组?

线程组中的stop、resume和suspend方法会导致安全问题,如死锁,这些方法已经被官方废弃。

线程组的功能相对有限,它无法在运行时对线程进行高级操作,如方法注入或暂停线程等。

在实际开发中,线程组的机制相对笨重,不便于进行动态调度,这导致代码难以扩展。

对于线程管理,推荐使用如Executor框架这样的现代工具,它们提供了更好的线程管理和资源控制,能够更有效地满足并发编程的需求。

Executor框架中的ThreadPoolExecutor类提供了线程池的实现,可以有效地管理和复用线程,减少系统开销。

18、为什么推荐使用Executor框架?

Executor框架将任务的提交与执行分离,提供了一种更加灵活和可扩展的方式来管理线程。它允许开发者专注于任务的实现逻辑,而不必关心任务的执行细节。

通过Executor框架,可以轻松地将任务异步执行,从而提高程序的效率和响应性。

Future接口允许获取异步任务的执行结果,提供了检查任务是否完成、等待任务完成以及获取任务结果的方法。这使得可以灵活地处理异步计算的结果,包括可能的异常处理。

除了基本的线程池实现,Executor框架还提供了ScheduledThreadPoolExecutor类,支持定时或周期性执行任务。

19Executor Executors 有什么区别?

Executor是一个接口,定义了一个线程池的核心方法execute(),用于提交任务到线程池中执行。它只包含一个execute(Runnable command)方法,用于执行给定的任务。

Executors 是一个工具类,提供了一些静态工厂方法来创建不同类型的ExecutorService实例。这些方法包括newFixedThreadPool、newCachedThreadPool等,它们提供了对ThreadPoolExecutor的封装,生成ExecutorService的具体实现类。

在实际使用中,通常不需要直接与Executor接口打交道,而是通过Executors类提供的方法来获取一个具体的ExecutorService实例。

20、用户线程与守护线程有什么区别?

在Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程) 。

用户线程是最常见的线程,比如通过main方法启动,就会创建一个用户线程。

Daemon的作用是为其他线程的运行提供便利服务,守护线程最典型的应用就是 GC (垃圾回收器),它就是一个很称职的守护者。

JVM中的垃圾回收、JIT编译器线程就是最常见的守护线程。

只要有一个用户线程在运行,守护线程就会一直运行。只有所有的用户线程都结束的时候,守护线程才会退出。

编写代码时,也可以通过 thread.setDaemon(true) 指定线程为守护线程。

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

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

相关文章

PH47框架下BBDB飞控基础开发平台极简教程

1 硬件准备 1.1 一块WeAct 的Stm32F411核心板 1.2 2个USB-TTL模块。 1.3 Stm32开发所必须的如STlink烧写器。 1.4 必要的线材。 2 软件准备 2.1 Stm32开发所必备的Keil开发环境。 2.2 PH47框架代码&#xff0c;下载链接 2.3 CSS及BBDB 控制站工程&#xff0c;下载链接 2.4…

鸿蒙面试的一些可能问到的点

页面跳转 router 鸿蒙中跳转主要有两种&#xff0c;一种是router&#xff0c;一种是Navigation&#xff0c;官方推荐使用Navigation。 Router适用于模块间与模块内页面切换&#xff0c;通过每个页面的url实现模块间解耦。模块内页面跳转时&#xff0c;为了实现更好的转场动效…

7.2-I2C的DMA中断

I2C的DMA中断 请先阅读完I2C的普通中断模式以后再阅读本教程 i2c的DMA模式 1.添加通道 &#xff0c;添加后的参数保持默认 2.可以看到自动给我们DMA添加了中断向量。 保存后只需要将下面_ IT改为_ DMA即可 运行代码 i2c1) { aht20State 4; } } /* USER CODE END 0 */ 以上就…

ssm基于java的网上手机销售系统

系统包含&#xff1a;源码论文 所用技术&#xff1a;SpringBootVueSSMMybatisMysql 免费提供给大家参考或者学习&#xff0c;获取源码请私聊我 需要定制请私聊 目 录 目 录 III 1 绪论 1 1.1 研究背景 1 1.2 目的和意义 1 1.3 论文结构安排 2 2 相关技术 3 2.1 SSM框…

yolov5环境GPU搭建 ,用GPU跑polov5算法

win10NVIDIA GeForce RTX 3050torch1.13.1torchaudio0.13.1torchvision 0.14.1 cuda11.7python3.8cudnn8.7.0 在环境搭建中踩了许多坑&#xff0c;yolov5环境的搭建需要依赖很多环境&#xff0c;用cpu跑很容易跑单张识别&#xff0c;用GPU跑却踩了很多坑&#xff0c;不过GPU环…

Mac 备忘录妙用

之前使用 Windows 的过程中&#xff0c;最痛苦的事是没有一款可以满足我快速进行记录的应用 基本都得先打开该笔记软件&#xff0c;然后创建新笔记&#xff0c;最后才能输入&#xff0c;这么多步骤太麻烦了 在切换到 MacOS 之后&#xff0c;让我惊喜的就是自带的备忘录&#…

【java面经thinking】一

目录 类加载过程 加载&#xff1a; 连接 初始化 GC回收机制&#xff08;垃圾回收&#xff09; 区域 判断对象是否存活 回收机制 HashMap 类加载器 加载标识 加载机制 缓存 自定义加载器&#xff1a; JVM内存结构 常量池 string设置成final 按下网址发生 类加…

C语言有关结构体的知识(后有通讯录的实现)

一、结构体的声明 1.1 结构体的定义 结构体是一些值的集合&#xff0c;这些值被称为成员变量。结构的每个成员可以是不同的类型 1.2 结构体的声明 这里以描述一个学生为例&#xff1a; struct stu {char name[10];//名字int age;//年龄char id[20];//学号char sex[5];//性别 }…

TIM定时器(标准库)

目录 一. 前言 二. 定时器的框图 三. 定时中断的基本结构 四. TIM定时器相关代码 五. 最终现象展示 一. 前言 什么是定时器&#xff1f; 定时器可以对输入的时钟进行计数&#xff0c;并在计数值达到设定值时触发中断。 TIM定时器不仅具备基本的定时中断功能&#xff0c;而且…

【LeetCode】708. 循环有序列表的插入

目录 一、题目二、解法完整代码 一、题目 给定循环单调非递减列表中的一个点&#xff0c;写一个函数向这个列表中插入一个新元素 insertVal &#xff0c;使这个列表仍然是循环非降序的。 给定的可以是这个列表中任意一个顶点的指针&#xff0c;并不一定是这个列表中最小元素的…

2024免费mac苹果电脑清理垃圾软件CleanMyMac X4.15.8

对于苹果电脑用户来说&#xff0c;设备上积累的垃圾文件可能会导致存储空间变得紧张&#xff0c;影响电脑的性能和使用体验。尤其是那些经常下载和安装新应用、编辑视频或处理大量照片的用户&#xff0c;更容易感受到存储空间的压力。面对这种情况&#xff0c;寻找一种有效的苹…

springboot3使用Excel导入数据库数据

一、导入依赖 <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml --><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.3.0</version></dependency> 二、…

Xilinx远程固件升级(二)——STARTUPE2原语的使用

通过&#xff08;一&#xff09;可以看出&#xff0c;对于远程固件升级实际上是通过调用flash不同区域的bit实现&#xff0c;通过golden image和update image共同保障了系统的稳定性。在项目中如果将flash的时钟直接绑定FPGA后进行约束&#xff0c;在综合编译时是无法通过的。这…

Spark:DataFrame介绍及使用

1. DataFrame详解 DataFrame是基于RDD进行封装的结构化数据类型&#xff0c;增加了schema元数据&#xff0c;最终DataFrame类型在计算时&#xff0c;还是转为rdd计算。DataFrame的结构化数据有Row&#xff08;行数据&#xff09;和schema元数据构成。 Row 类型 表示一行数据 …

MySQL 8.4修改初始化后的默认密码

MySQL 8.4修改初始化后的默认密码 &#xff08;1&#xff09;初始化mysql&#xff1a; mysqld --initialize --console &#xff08;2&#xff09;之后,mysql会生成一个默认复杂的密码&#xff0c;如果打算修改这个密码&#xff0c;可以先用旧密码登录&#xff1a; mysql -u…

Redis set类型 zset类型

set类型 类型介绍 集合类型也是保存多个字符串类型的元素的&#xff0c;但和列表类型不同的是&#xff0c;集合中 1&#xff09;元素之间是⽆序 的 2&#xff09;元素不允许重复 ⼀个集合中最多可以存储 个元素。Redis 除了⽀持 集合内的增删查改操作&#xff0c;同时还⽀持多…

【图书推荐】《R语言医学数据分析实践》

本书重点 梅俏、卢龙、丁健、张晟、黄龙、胡志坚、张琼瑶、林志刚等业内专家联袂推荐。 以公共医学数据为例&#xff0c;精选大量的实用案例&#xff0c;深入浅出地介绍统计建模分析方法。 帮助读者解决医学数据分析中遇到的实际问题。 通过实际操作引导读者入门科研论文数…

生信分析流程:从数据准备到结果解释的完整指南

介绍 生物信息学&#xff08;生信&#xff09;分析是一个复杂的过程&#xff0c;涉及从数据准备到结果解释的多个步骤。随着高通量测序技术的发展和生物数据的迅猛增长&#xff0c;了解和掌握生信分析的标准流程变得尤为重要。这不仅有助于提高分析的准确性&#xff0c;还能优…

HarmonyOS NEXT 应用开发实战(五、页面的生命周期及使用介绍)

HarmonyOS NEXT是华为推出的最新操作系统&#xff0c;arkUI是其提供的用户界面框架。arkUI的页面生命周期管理对于开发者来说非常重要&#xff0c;因为它涉及到页面的创建、显示、隐藏、销毁等各个阶段。以下是arkUI页面生命周期的介绍及使用举例。 页面的生命周期的作用 页面…

7-I2C与AHT20温湿度传感器

I2C与AHT20温湿度传感器 嵌入式领域另一种常见的通信IIC通信&#xff0c;并用其与AHT20传感器进行交互&#xff0c;获取房间的温度与湿度。 I2C有一条用于传递数据的数据线称为SDA&#xff08;Serial Data&#xff09;&#xff0c;另一条是用于提供同步时钟脉冲的时钟线SCL&am…