谷粒商城实战笔记-193~194-商城业务-多线程-线程池

embedded/2024/12/22 13:21:39/

文章目录

  • 一,193-商城业务-异步-异步复习
    • 1. 继承`Thread`类
    • 2. 实现`Runnable`接口
    • 3. 实现`Callable`接口结合`FutureTask`
    • 4. 使用线程池
  • 二,194-商城业务-异步-线程池详解
    • 1,线程池七大参数
    • 2,面试题
    • 3,Executors能创建的4中线程池
      • FixedThreadPool
      • CachedThreadPool
      • SingleThreadExecutor
      • ScheduledThreadPoolExecutor

一,193-商城业务-异步-异步复习

Java中使用线程的4种方式包括:

  • 继承Thread
  • 实现Runnable接口
  • 实现Callable接口结合FutureTask使用
  • 使用线程池。

1. 继承Thread

继承Thread类并重写run方法来定义线程执行的任务。这种方式简单直观,但存在一些限制。

代码示例

java">public class ThreadExample1 extends Thread {@Overridepublic void run() {System.out.println("ThreadExample1 is running.");}
}// 使用
ThreadExample1 thread = new ThreadExample1();
thread.start();

问题:继承Thread类会强制要求类继承自Thread,这限制了类的继承结构,因为Java不支持多重继承。

2. 实现Runnable接口

通过实现Runnable接口,可以避免继承Thread类的限制,因为Java允许一个类实现多个接口。

代码示例

java">public class RunnableExample1 implements Runnable {@Overridepublic void run() {System.out.println("RunnableExample1 is running.");}
}// 使用
RunnableExample1 runnable = new RunnableExample1();
new Thread(runnable).start();

问题:与继承Thread类类似,这种方式不能获取线程执行的返回值,也不能很好地控制资源。

3. 实现Callable接口结合FutureTask

Callable接口允许任务有返回值,并且可以通过FutureTask来管理线程的生命周期和结果。

代码示例

java">public class CallableExample1 implements Callable<Integer> {@Overridepublic Integer call() {return 100;}
}// 使用
FutureTask<Integer> futureTask = new FutureTask<>(new CallableExample1());
new Thread(futureTask).start();
try {Integer result = futureTask.get(); // 阻塞等待结果System.out.println("CallableExample1 returned: " + result);
} catch (InterruptedException | ExecutionException e) {e.printStackTrace();
}

问题:尽管这种方式可以获取返回值,但创建和管理线程的开销仍然存在。

4. 使用线程池

线程池提供了一种高效的方式来管理线程,它可以复用线程,减少创建和销毁线程的开销,同时可以控制并发级别。

代码示例

java">import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolExample {public static void main(String[] args) {ExecutorService executorService = Executors.newFixedThreadPool(10); // 创建线程池Runnable task = () -> System.out.println("Task is running in thread pool.");executorService.submit(task); // 提交任务到线程池// 执行完毕后关闭线程池executorService.shutdown();}
}

优势

  • 资源控制:线程池可以控制并发线程的数量,有效管理资源。
  • 性能稳定:通过复用线程,减少了线程创建和销毁的开销,提高了性能。
  • 易于管理:线程池提供了统一的接口来提交和管理任务,简化了代码。

在实际开发中,推荐使用线程池来执行多线程任务,因为它提供了更好的资源管理和性能优势。

前三种方式虽然在某些简单场景下可以使用,但在需要高效资源管理和复杂任务调度的现代应用程序中,它们往往不够灵活和高效。

二,194-商城业务-异步-线程池详解

1,线程池七大参数

线程池(ThreadPoolExecutor)是Java并发编程中用于管理线程的一个核心组件。它允许你复用线程,从而减少因频繁创建和销毁线程而带来的开销。以下是线程池的七个主要参数,这些参数在创建线程池时可以进行配置:

  1. corePoolSize:线程池的基本大小,即在没有任务执行时,线程池中保留的线程数量。如果允许核心线程超时(通过设置allowCoreThreadTimeOuttrue),则即使线程池中的线程是空闲的,它们也会在一定时间后终止。

  2. maximumPoolSize:线程池中允许的最大线程数。如果任务队列满了,线程池会尝试创建新的线程,直到达到这个数目。

  3. keepAliveTime:当线程池中的线程数量超过corePoolSize时,多余的空闲线程能等待新任务的最长时间。如果在这个时间内没有新任务到达,这些线程将被终止。

  4. unitkeepAliveTime参数的时间单位,常见的时间单位有TimeUnit.SECONDSTimeUnit.MILLISECONDS等。

  5. workQueue:一个阻塞队列,用于存储等待执行的任务。这个队列只保存通过execute(Runnable)方法提交的Runnable任务。

  6. threadFactory:一个线程工厂,用于创建新线程。通过自定义线程工厂,你可以对线程的创建过程进行控制,例如设置线程的名称、优先级等。

  7. handler:当线程池饱和(即线程数量达到maximumPoolSize且任务队列已满)时,使用的饱和策略。饱和策略定义了如何处理无法立即执行的任务,常见的饱和策略有:

    • ThreadPoolExecutor.AbortPolicy:抛出RejectedExecutionException来拒绝新任务的处理。
    • ThreadPoolExecutor.CallerRunsPolicy:调用执行任务的线程(提交任务的线程)来运行当前任务。
    • ThreadPoolExecutor.DiscardPolicy:直接丢弃无法处理的任务。
    • ThreadPoolExecutor.DiscardOldestPolicy:丢弃任务队列中最老的任务,然后尝试再次提交当前任务。

这些参数共同定义了线程池的行为和性能。正确地配置这些参数对于优化应用程序的并发性能至关重要。例如,如果corePoolSizemaximumPoolSize设置得太高,可能会导致资源竞争和上下文切换的开销;如果设置得太低,则可能无法充分利用多核处理器的优势。同样,workQueue的选择也会影响线程池的吞吐量和延迟特性。

2,面试题

下面是一个面试题。
在这里插入图片描述

当有100个并发请求进入线程池时,线程池会按照以下步骤进行操作:

  1. 首先,线程池会尝试使用其核心线程来处理请求。由于核心线程数为7,所以线程池会立即启动7个线程来处理这7个请求。

  2. 如果还有更多请求进来,并且核心线程都在忙于处理其他请求,那么这些额外的请求会被放入队列中等待处理。由于队列容量为50,所以最多可以存放50个请求。

  3. 当队列也满了后,线程池会尝试创建新的非核心线程来处理请求。由于最大线程数为20,所以最多可以创建13个非核心线程。

  4. 如果此时仍然有请求进来,并且所有的线程都在忙于处理其他请求,那么线程池可能会选择拒绝这些请求。具体的行为取决于线程池的饱和策略。

3,Executors能创建的4中线程池

在实际开发过程中,一般用Executors创建线程池,Executors相当于一个工厂类,创建各种各样的线程池对象。

  1. FixedThreadPool:

    • 类型:固定大小的线程池。
    • 特点:线程池中的线程数量是固定的。当一个线程完成任务后,它会从队列中获取新的任务来执行。这种线程池能够保证程序的资源占用相对稳定。
    • 用途:适用于需要控制线程数量的场景,如后台任务处理、定时任务等。
  2. CachedThreadPool:

    • 类型:可缓存的线程池。
    • 特点:线程池的大小没有限制,可以根据需要动态地调整线程的数量。空闲的线程会在一段时间后自动终止。
    • 用途:适用于执行大量短小的任务,如网络I/O操作、计算密集型任务等。
  3. SingleThreadExecutor:

    • 类型:单线程的线程池。
    • 特点:线程池只有一个线程,确保所有任务按照指定顺序执行。
    • 用途:适用于需要保证任务顺序执行的场景,例如数据更新、文件写入等。
  4. ScheduledThreadPoolExecutor:

    • 类型:支持定时任务的线程池。
    • 特点:线程池可以调度任务以定期或延迟的方式执行。
    • 用途:适用于需要定期执行任务或延时执行任务的场景,如计划任务、周期性检查等。

下面是这四种线程池的具体实现方式:

FixedThreadPool

java">ExecutorService fixedThreadPool = Executors.newFixedThreadPool(nThreads);

CachedThreadPool

java">ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

SingleThreadExecutor

java">ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

ScheduledThreadPoolExecutor

java">ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(nThreads);

其中,nThreads 表示线程池中的线程数量。对于 newFixedThreadPoolnewScheduledThreadPool,这个值是必需的,而对于 newSingleThreadExecutornewCachedThreadPool,则不需要指定线程数量。


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

相关文章

Linux 内核源码分析---传输层分析

套接字分析 每个操作系统都必须提供网络子系统入口及API&#xff0c;Linux内核网络子系统提供的标准 POSIX 套接字API向用户提供接口。在 Linux 中传输层之上的一切都属于用户空间。 Linux 也遵循 Unix 范式&#xff08;一切皆为文件&#xff09;&#xff0c;因此套接字也与文…

儿童一直没有语言是不是自闭症?

在探讨儿童发展的广阔领域中&#xff0c;语言能力的出现与发展无疑是家长和社会关注的焦点之一。当发现孩子迟迟未能开口说话&#xff0c;或是语言表达能力远远落后于同龄儿童时&#xff0c;许多家庭不禁会担忧&#xff1a;这是否意味着孩子患有自闭症&#xff1f;诚然&#xf…

WordPress 中 cURL 请求出现 504 网关超时错误的解决方法

错误原因 504网关超时错误通常发生在服务器作为网关或代理&#xff0c;不能在规定的时间内得到响应时。在WordPress中&#xff0c;这可能是因为目标服务器响应过慢&#xff0c;或请求的队列过长导致的。 解决方案 首先&#xff0c;您应该检查您的cURL请求是否设置了一个合理的…

数据结构 之 常见的树

文章目录 树的概念术语&#xff08;以二叉树举例&#xff09; 二叉树遍历满二叉树完全二叉树二叉搜索树&#xff08;有序二叉树&#xff09; 哈夫曼树术语补充WPL的比较&#xff08;直接上图&#xff09;哈夫曼树的构建过程哈夫曼编码 非平衡树 & 平衡树(avl树)非平衡树转平…

JVM分代回收

JVM分代回收 堆中分为两份:新生代和老年代(1:2) 新生代 新生代的内部分为了三个区域 Eden区,From区,To区[8:1:1] 当eden区内存不足时,就会使用可达性分析算法进行标记 标记eden区和from区的存活对象 将这些对象复制到to区,对eden区和from区进行清除 如果eden下次又出现…

Android 启动动画太生硬

跟 android:launchMode"singleTask"属性无关系 请禁用路由 ARouter.getInstance() .build(Routes.Main.MAIN) .withTransition(R.anim.activity_anim_in, R.anim.activity_anim_out).navigation() 正确做法是 val intent Intent(thisSplashActivity,MainActivit…

xss之DOM破坏

文章目录 DOM破坏漏洞的复现https://xss.pwnfunction.com/基于bp学院DOM破坏漏洞复现思路分析实现 常见的xss触发的标签没有过滤的情况存在过滤的情况 DOM破坏 DOM破坏就是⼀种将 HTML 代码注⼊⻚⾯中以操纵 DOM 并最终更改⻚⾯上 JavaScript ⾏为的技术。 在⽆法直接 XSS的情…

EXCEL跨文件查询,指定条件列,返回满足条件的指定列

EXCEL跨文件查询&#xff0c;指定条件列&#xff0c;返回满足条件的指定列 Private Sub cmd_find_from_workbooks_Click() Dim S_Cols As String, thePath As String, Sor_Col As Integer, sz_Cols As Variant S_Cols T_jieguo_cols.Text sz_Cols Split(S_Cols, ",&quo…