2024年150道高频Java面试题(三十二)

embedded/2024/12/22 20:46:00/

63. 线程的 run() 和 start() 有什么区别?

在Java中,run()方法和start()方法是线程操作中的两个核心方法,它们来自于Thread类。

run()方法:

  • run()方法是一个线程的实际执行代码所在的方法。
  • 它是一个由Runnable接口定义的抽象方法,因此任何实现Runnable接口的类都需要覆盖这个方法。
  • run()方法被调用时,它会在当前线程的上下文中执行(即,如果直接调用一个线程对象的run()方法,它会在调用它的线程中运行,而不是在新线程中运行)。
  • run()方法可以多次调用,它仅仅是一个普通的方法调用。

start()方法:

  • start()方法是用来启动新线程并执行run()方法中的代码的。
  • 当调用start()方法时,它会创建一个新的线程,然后在这个新线程中调用run()方法。
  • 一个线程对象只能调用一次start()方法,多次调用会抛出IllegalThreadStateException
  • start()方法是由JVM调用来启动线程的,而不是由开发者在代码中直接调用的。

以下是两者的简单对比表格:

对比项run()方法start()方法
调用目的执行线程任务启动一个新线程
调用次数可以多次调用只能调用一次
调用效果在当前线程中执行创建新线程,在新线程中执行run()
异常处理直接在调用线程中抛出任何未捕获异常由新线程处理
方法来源实现Runnable接口时覆盖继承Thread类时使用

以下是一个简单的代码示例说明这两个方法的不同:

java">class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("Thread is running: " + Thread.currentThread().getName());}
}public class ThreadExample {public static void main(String[] args) {MyRunnable myRunnable = new MyRunnable();// 通过start()方法启动新线程Thread thread = new Thread(myRunnable);thread.start(); // 正确使用start()方法启动线程// 直接调用run()方法,不会启动新线程myRunnable.run(); // 这将在main线程中执行,而不是新线程// 以下调用是错误的,会抛出异常// thread.start(); // 不能重复调用start()方法}
}

在这个示例中,我们创建了一个实现Runnable接口的类MyRunnable,并在主方法中创建了Thread对象。调用start()方法将创建一个新线程,并在该线程中调用MyRunnablerun()方法。而直接调用run()方法则不会创建新线程,而是在当前线程(这里是主线程)中执行run()方法中的代码。

64. 创建线程池有哪几种方式?

在Java中,创建线程池可以通过几种方式实现,通常使用java.util.concurrent.Executors工厂类或者直接实例化java.util.concurrent.ThreadPoolExecutor。以下是几种常见的创建线程池的方式:

  1. 使用Executors
    • 固定大小的线程池:使用Executors.newFixedThreadPool(int nThreads)创建一个线程池,该线程池的线程数量固定,如果某个线程因为异常结束,那么会补充一个新的线程。
    • 单线程的Executor:使用Executors.newSingleThreadExecutor()创建一个单线程的执行器,所有提交的任务都会被串行执行。
    • 可缓存的线程池:使用Executors.newCachedThreadPool()创建一个根据需要创建新线程的线程池,对于旧线程,如果60秒没有被使用就将被回收。
    • 计划任务的线程池:使用Executors.newScheduledThreadPool()创建一个可以定时执行任务的线程池。
  2. 直接使用ThreadPoolExecutor构造函数
    • 可以通过直接实例化ThreadPoolExecutor类来创建自定义的线程池。这需要指定以下参数:
      • int corePoolSize:核心线程数。
      • int maximumPoolSize:最大线程数。
      • long keepAliveTime:非核心线程的空闲存活时间。
      • TimeUnit unit:存活时间的单位。
      • BlockingQueue<Runnable> workQueue:工作队列。
      • ThreadFactory threadFactory:可选,用于创建新线程的工厂。
      • RejectedExecutionHandler handler:可选,当任务无法执行时的策略。
  3. 使用ForkJoinPool
    • 对于需要大量计算并且能够进行分治任务拆分的应用,可以使用ForkJoinPool。它适用于递归算法或者可以递归分解为更小任务的大任务。

以下是使用ThreadPoolExecutor创建线程池的示例代码:

java">import java.util.concurrent.*;public class CustomThreadPool {public static void main(String[] args) {// 创建自定义线程池ThreadPoolExecutor executor = new ThreadPoolExecutor(2, // 核心线程数4, // 最大线程数60, // 非核心线程空闲存活时间TimeUnit.SECONDS, // 存活时间单位new ArrayBlockingQueue<>(10) // 工作队列);// 提交任务for (int i = 0; i < 10; i++) {executor.submit(() -> {System.out.println("执行任务: " + Thread.currentThread().getName());});}// 关闭线程池executor.shutdown();}
}

以上就是创建线程池的几种方式及其简单示例。注意,在实际的生产环境中,建议直接使用ThreadPoolExecutor构造函数来精确控制线程池的行为,避免因为默认参数而引发的潜在问题。

有帮助请点赞收藏呀~

领【150 道精选 Java 高频面试题】请 go 公众号:码路向前 。


http://www.ppmy.cn/embedded/1882.html

相关文章

MySQL怎么排查慢sql语句,排查后一般怎么优化

当排查和优化MySQL中的慢SQL语句时&#xff0c;通常会涉及以下步骤&#xff1a; 识别慢查询&#xff1a; 使用MySQL的慢查询日志&#xff08;slow query log&#xff09;来记录执行时间超过一定阈值的SQL语句。你可以通过修改MySQL配置文件来启用慢查询日志&#xff0c;并设置阈…

桌面应用程序测试与网站应用程序测试

不断发展的技术使应用程序面临众多威胁&#xff0c;尤其是在更新期间。计算机系统上有两种基本的应用程序类型&#xff1a;桌面应用程序和网站应用程序。由于这些应用程序运行在不同的环境中&#xff0c;因此需要相应的应用程序测试方法。 桌面应用程序测试就是对桌面应用程序…

springCloud项目打包 ,maven package或install打包报错

解决思路一&#xff1a; <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>2.3.7.RELEASE</version></plugin><plugin>&…

react结合Redux实现全局状态管理

React与Redux结合使用&#xff0c;可以为React应用提供集中式的状态管理和复杂的业务逻辑处理能力。以下是React中使用Redux的基本步骤和关键概念&#xff1a; 安装所需库 确保已经安装了React和ReactDOM。然后安装Redux及其配套库&#xff1a; npm install redux react-redu…

迁移强化学习论文笔记(一)(Successor Features)

迁移强化学习论文笔记&#xff08;一&#xff09;&#xff08;Successor Features&#xff09; 一.Background and problem formulation M ≡ ( S , A , p , R , γ ) M \equiv(\mathcal{S}, \mathcal{A}, p, R, \gamma) M≡(S,A,p,R,γ) S \cal S S:状态空间 A \cal A A&…

C语言中的数据结构--双向链表

前言 上一节我们已经学习完了单链表&#xff08;单向不带头不循环链表&#xff09;的所有内容&#xff0c;我们在链表的分类里面知道了&#xff0c;链表分为单向的和双向的&#xff0c;那么本节我们就来进行双向链表&#xff08;带头双向循环链表&#xff09;的学习&#xff0c…

构建现代网页的引擎:WebKit架构揭秘

在网络信息迅猛增长的今天&#xff0c;浏览器已经成为我们接触世界的重要窗口。而在浏览器的核心&#xff0c;有一个强大的引擎在默默地支撑着网页的渲染和执行&#xff0c;这就是WebKit。 WebKit的核心组件 WebKit作为开源浏览器引擎&#xff0c;由苹果公司发展而来&#x…

结合SOCKS5代理、代理IP与网络安全促进跨界电商和游戏产业发展

一、引言 在全球化的大背景下&#xff0c;数字技术的应用已成为企业出海战略的重要组成部分。尤其是在跨界电商和游戏行业&#xff0c;通过有效利用SOCKS5代理、代理IP和网络安全技术&#xff0c;不仅可以突破地域限制&#xff0c;还能保障数据的安全和用户的隐私。本文旨在探讨…