Java——多线程(6/9):线程池、处理Runnable、Callable任务(认识线程池-线程池的工作原理,ThreadPoolExecutor构造器)

目录

认识线程池

介绍

线程池的工作原理

如何创建线程池 

介绍

ThreadPoolExecutor构造器

代码实例 

线程池的注意事项

线程池处理Runnable任务

ExecutorService的常用方法

代码实例

新任务拒绝策略

线程池处理Callable任务

ExecutorService的常用方法

代码实例


认识线程池

介绍

什么是线程池

  • 线程池就是一个可以复用线程的技术

不使用线程池的问题

  • 用户每发起一个请求,后台就需要创建一个新线程来处理,下次新任务来了肯定又要创建新线程处理的,而创建新线程的开销是很大的,并且请求过多时,肯定会产生大量的线程出来,这样会严重影响系统的性能。

线程池的工作原理

任务对象实现接口:

  • Runnable
  • Callable

由于线程池可以控制线程的数量,又可以控制那些任务的数量,因此它不会因为这些线程过多或者任务过多而导致把系统资源耗尽,引起系统瘫痪的风险。整体看是可以提高系统的工作性能的。

如何创建线程池 

介绍

谁代表线程池?

  • JDK5.0起提供了代表线程池的接口:ExecutorService。

如何得到线程池对象?

  • 方式一:使用ExecutorService的实现类ThreadPoolExecutor创建一个线程池对象。

  • 方式二:使用Executors(线程池的工具类)调用方法返回不同特点的线程池对象。

ThreadPoolExecutor构造器

public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory,RejectedExecutionHandler handler);
  • 参数一:corePoolSize:指定线程池的核心线程的数量。
  • 参数二:maximumPoolSize:指定线程池的最大线程数量。
  • 参数三:keepAliveTime:指定临时线程的存活时间。
  • 参数四:unit:指定临时线程存活的时间单位(秒、分、时、天)
  • 参数五:workQueue:指定线程池的任务队列。
  • 参数六:threadFactory:指定线程池的线程工厂。
  • 参数七:handler:指定线程池的任务拒绝策略(线程都在忙,任务队列也满了的时候,新任务来了该怎么处理)

以餐厅作为例子:

代码实例 

import java.util.concurrent.*;/*掌握线程池的创建*/
public class ThreadPoolTest1 {public static void main(String[] args) {//1.通过ThreadPoolExecutor创建一个线程池对象ExecutorService pool = new ThreadPoolExecutor(3,5,8,TimeUnit.SECONDS,new ArrayBlockingQueue<>(4), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());}
}

线程池的注意事项

1、临时线程什么时候创建?

  • 新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建临时线程。

2、什么时候会开始拒绝新任务?

  • 核心线程和临时线程都在忙,任务队列也满了,新的任务过来的时候才会开始拒绝任务。

线程池处理Runnable任务

ExecutorService的常用方法

方法名称说明
void execute(Runnable command)执行 Runnable 任务
Future<T> submit(Callable<T> task)执行Callable任务,返回未来任务对象,用于获取线程返回的结果
void shutdown()等全部任务执行完毕后,再关闭线程池!
List<Runnable> shutdownNow()立刻关闭线程池,停止正在执行的任务,并返回队列中未执行的任务

代码实例

public class MyRunnable implements Runnable{@Overridepublic void run() {//线程类执行的任务System.out.println(Thread.currentThread().getName() + "--> 输出233!");try {Thread.sleep(1000);} catch (Exception e) {e.printStackTrace();}}
}
import java.util.concurrent.*;public class ThreadPoolTest1 {public static void main(String[] args) {//1.通过ThreadPoolExecutor创建一个线程池对象ExecutorService pool = new ThreadPoolExecutor(3,5,8,TimeUnit.SECONDS,new ArrayBlockingQueue<>(4), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());Runnable target = new MyRunnable();pool.execute(target);   //线程池会自动创建一个新线程,自动处理这个任务,自动执行pool.execute(target);   //线程池会自动创建一个新线程,自动处理这个任务,自动执行pool.execute(target);   //线程池会自动创建一个新线程,自动处理这个任务,自动执行pool.execute(target);   //复用前面的核心线程pool.execute(target);   //复用前面的核心线程pool.shutdown();    //等待线程池的全部任务全部执行完毕后,再关闭线程
//        pool.shutdownNow(); //立即关闭线程池!不管任务是否执行完毕}
}

运行结果:

临时线程的创建时机

import java.util.concurrent.*;public class ThreadPoolTest1 {public static void main(String[] args) {//1.通过ThreadPoolExecutor创建一个线程池对象ExecutorService pool = new ThreadPoolExecutor(3,5,8,TimeUnit.SECONDS,new ArrayBlockingQueue<>(4), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());Runnable target = new MyRunnable();pool.execute(target);   //线程池会自动创建一个新线程,自动处理这个任务,自动执行pool.execute(target);   //线程池会自动创建一个新线程,自动处理这个任务,自动执行pool.execute(target);   //线程池会自动创建一个新线程,自动处理这个任务,自动执行pool.execute(target);pool.execute(target);pool.execute(target);pool.execute(target);//占满任务队列,到了临时线程的创建时机了pool.execute(target);pool.execute(target);pool.shutdown();    //等待线程池的全部任务全部执行完毕后,再关闭线程
//        pool.shutdownNow(); //立即关闭线程池!不管任务是否执行完毕}
}

运行结果: 

新任务的拒绝时机

package user.ThreadTest;import java.util.concurrent.*;/*掌握线程池的创建*/
public class ThreadPoolTest1 {public static void main(String[] args) {//1.通过ThreadPoolExecutor创建一个线程池对象ExecutorService pool = new ThreadPoolExecutor(3,5,8,TimeUnit.SECONDS,new ArrayBlockingQueue<>(4), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());Runnable target = new MyRunnable();pool.execute(target);   //线程池会自动创建一个新线程,自动处理这个任务,自动执行pool.execute(target);   //线程池会自动创建一个新线程,自动处理这个任务,自动执行pool.execute(target);   //线程池会自动创建一个新线程,自动处理这个任务,自动执行pool.execute(target);pool.execute(target);pool.execute(target);pool.execute(target);//占满任务队列,到了临时线程的创建时机了pool.execute(target);pool.execute(target);//再创建,就到了新任务的拒绝时机了pool.execute(target);pool.shutdown();    //等待线程池的全部任务全部执行完毕后,再关闭线程
//        pool.shutdownNow(); //立即关闭线程池!不管任务是否执行完毕}
}

运行结果:

新任务拒绝策略

策略详解
ThreadPoolExecutor.AbortPolicy丢弃任务并抛出RejectedExecutionException异常。是默认的策略
ThreadPoolExecutor.DiscardPolicy丢弃任务,但是不抛出异常这是不推荐的做法
ThreadPoolExecutor.DiscardoldestPolicy抛弃队列中等待最久的任务然后把当前任务加入队列中
ThreadPoolExecutor.CallerRunsPolicy由主线程负责调用任务的run0方法从而绕过线程池直接执行

改成ThreadPoolExecutor.CallerRunsPolicy策略:

改完拒绝策略,就不会报之前的那个错,

运行结果变为: 

线程池处理Callable任务

ExecutorService的常用方法

方法名称说明
void execute(Runnable command)执行 Runnable 任务
Future<T> submit(Callable<T> task)执行Callable任务,返回未来任务对象,用于获取线程返回的结果
void shutdown()等全部任务执行完毕后,再关闭线程池!
List<Runnable> shutdownNow()立刻关闭线程池,停止正在执行的任务,并返回队列中未执行的任务

代码实例

import java.util.concurrent.Callable;public class MyCallable implements Callable<String> {private int n;public MyCallable(int n){this.n = n;}//2.重写call方法@Overridepublic String call() throws Exception {//描述线程的任务,返回线程执行返回后的结果//需求:求1-n的和返回int sum = 0;for (int i = 0; i <= n; i++) {sum += i;}return Thread.currentThread().getName() + "求出了1-" + n + "的和是:" + sum;}
}
import java.util.concurrent.*;public class ThreadPoolTest2 {public static void main(String[] args) throws Exception{//1、通过ThreadPooLExecutor创建一个线程池对象。ExecutorService pool = new ThreadPoolExecutor(3,5,8,TimeUnit.SECONDS,new ArrayBlockingQueue<>(4), Executors.defaultThreadFactory(),new ThreadPoolExecutor.CallerRunsPolicy());//2、使用线程处理CaLLabLe任务。Future<String> f1 = pool.submit(new MyCallable(100));Future<String> f2 = pool.submit(new MyCallable(200));Future<String> f3 = pool.submit(new MyCallable(300));Future<String> f4 = pool.submit(new MyCallable(400));System.out.println(f1.get());System.out.println(f2.get());System.out.println(f3.get());System.out.println(f4.get());pool.shutdown();    //等待线程池的全部任务全部执行完毕后,再关闭线程}
}

 运行结果


END


学习自:黑马程序员——Java课程

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何从智联招聘网站快速抓取职位详情?两大技巧揭秘

摘要&#xff1a; 本文将揭秘如何利用Python爬虫技术&#xff0c;高效且合法地从智联招聘网站抓取职位详情信息。通过实战示例&#xff0c;展现两大核心技巧&#xff0c;助你在大数据时代抢占先机&#xff0c;为你的市场分析、人才研究提供强大支持。 一、引言&#xff1a;数据…

排序算法:冒泡排序,golang实现

目录 前言 冒泡排序 代码示例 1. 算法包 2. 冒泡排序代码 3. 模拟排序 4. 运行程序 5. 从大到小排序 循环细节 外层循环 内层循环 总结 循环次数测试 假如 10 条数据进行排序 假如 20 条数据进行排序 假如 30 条数据进行排序 假设 5000 条数据&#xff0c;对比…

荒原之梦考研:专科考研成功的可能性大吗?

专科还是本科不是决定考研能否成功的关键因素&#xff0c;决定考研能否成功的关键因素是自己是否有清晰的规划、是否有足够的专注能力&#xff0c;以及是否能够吃得了考研的“苦”。 首先要有清晰的规划&#xff0c;比如说&#xff0c;不是我们每个人足够努力就都能考上 TOP1 …

很简单的Win10+Win7双系统教程|UEFI篇

前言 前段时间有写过一篇关于Windows10Windows7双系统安装教程&#xff0c;但这个教程为了比较保险&#xff0c;就进入了WinPE维护系统进行操作。 但有很多小伙伴就有点搞不懂了&#xff0c;都不知道WinPE是什么系统&#xff0c;也不知道怎么去解决这个问题。 今天咱们就来讲…

centos7部署智能dns实战应用

主DNS&#xff1a;192.168.101.129 备DNS&#xff1a;192.168.101.128 原理&#xff1a; 一、下载软件 bind-9.17.9.tar.xz的下载地址&#xff1a;https://ftp.isc.org/isc/bind9/9.17.9/bind-9.17.9.tar.xz。更多的bind版本可以从https://ftp.isc.org/isc/bind9/下载。 二&a…

【深入探秘Hadoop生态系统】全面解析各组件及其实际应用

深入探秘Hadoop生态系统&#xff1a;全面解析各组件及其实际应用 引言 在大数据时代&#xff0c;如何高效处理和存储海量数据成为企业面临的重大挑战。根据Gartner的统计&#xff0c;到2025年&#xff0c;全球数据量将达到175泽字节&#xff08;ZB&#xff09;&#xff0c;传…

学习安卓开发遇到的问题

问题1&#xff1a;学习禁用与恢复按钮中&#xff1a; java代码报错&#xff1a;报错代码是 R.id.btn_enable;case R.id.btn_disable;case R.id.btn_test: 代码如下&#xff1a;&#xff08;实现功能在代码后面&#xff09; package com.example.apptest;import static java.…

【时时三省】unity test 测试框架 介绍(适用于C语言进行测试的)

1&#xff0c;关于 unity test 测试框架的介绍 unity test 是 ThrowTheSwitch.org 的一个主要工程。它是专注于为嵌入式工具链而生的C语言单元测试框架。它可以适用于大工程或者小工程都可以。它的核心文件是一个.c文件和两个头文件。 备注&#xff1a; 下载源码地址&#xff…

应急响应-Web3

打开虚拟机之后&#xff0c;运行解题系统&#xff1a; 共有三个问题&#xff01; 攻击者的两个IP地址 首先我们看到机器的桌面上还是存在phpstudy&#xff0c;那就还是先去看看是不是从web层面进行的攻击&#xff0c;上传webshell从而getshell。 利用D盾尝试对phpstudy目录进…

WordPress资源下载类主题 CeoMax-Pro_v7.6绕授权开心版

CeoMax-Pro强大的功能 在不久的将来Ta能实现你一切幻想&#xff01;我们也在为此而不断努力。适用于资源站、下载站、交易站、素材站、源码站、课程站、cms等等等等&#xff0c;Ta 为追求极致的你而生。多风格多样式多类型多行业多功能 源码下载&#xff1a;ceomax-pro7.6.zip…

【系统架构设计师】二十四、安全架构设计理论与实践②

目录 三、系统安全体系架构规划框架 3.1 信息系统安全体系规划 3.2 信息系统安全规划框架 3.2.1 信息系统安全规划依托企业信息化战略规划 3.2.2 信息系统安全规划需要围绕技术安全、管理安全、组织安全考虑 3.2.3 信息系统安全规划以信息系统与信息资源的安全保护为核心…

[环境配置]Pycharm:Failed to start [PowerShell.exe]

解决方法&#xff0c;点Local旁边的 号&#xff0c;点击Command Prompt&#xff0c;即可在Pycharm中呼出控制台。 如果要修改Command Prompt的启动时访问的cmd.exe的路径&#xff0c;可以去Settings→Tools→Terminal中&#xff0c;修改Shell Path实现&#xff0c;改为cmd.exe…

AWS开发人工智能:如何基于云进行开发人工智能AI

随着人工智能技术的飞速发展&#xff0c;企业对高效、易用的AI服务需求日益增长。Amazon Bedrock是AWS推出的一项创新服务&#xff0c;旨在为企业提供一个简单、安全的平台&#xff0c;以访问和集成先进的基础模型。本文中九河云将详细介绍Amazon Bedrock的功能特点以及其收费方…

117页PPT埃森哲-物流行业信息化整体规划方案

一、埃森哲-物流行业信息化整体规划方案 资料下载方式&#xff0c;请看每张图片右下角信息 埃森哲在物流行业信息化整体规划项目中的核心内容&#xff0c;旨在帮助物流企业通过信息技术的应用实现业务流程的优化、运营效率的提升以及市场竞争力的增强。以下是埃森哲在此类项目…

C语言指针(1)

目录 一、内存和地址 1、生活中的例子 2、内存的关系 二、指针变量和地址 1、&符号&#xff0c;%p占位符 2、一个简单的指针代码。 3、理解指针 4、解引用操作符 5、指针变量的大小。 三、指针变量类型的意义 1、指针解引用的作用 2、指针指针 3、指针-指针 4…

Python初学者必须掌握的基础知识点

Python初学者必须掌握的基础知识点包括数据类型与变量、控制结构&#xff08;条件语句和循环语句&#xff09;、基本数据结构&#xff08;列表、元组、字典、集合&#xff09;、函数与模块、以及字符串处理等。以下是对这些基础知识点及其对应代码的详细介绍&#xff1a; 1. …

利用Llama 3 API实现盈利:细节解析

随着人工智能技术的快速发展,基于大模型的服务成为了众多初创企业关注的焦点。Llama 3 API作为一种强大的语言模型接口,为小型公司提供了利用先进AI技术的机会。本文将探讨这些小公司如何通过Llama 3 API实现盈利,并分析其中的关键因素。 一、Llama 3 API性能概览 批处理输…

Golang | Leetcode Golang题解之第318题最大单词长度乘积

题目&#xff1a; 题解&#xff1a; func maxProduct(words []string) (ans int) {masks : map[int]int{}for _, word : range words {mask : 0for _, ch : range word {mask | 1 << (ch - a)}if len(word) > masks[mask] {masks[mask] len(word)}}for x, lenX : ra…

设计模式 - Singleton pattern 单例模式

文章目录 定义单例模式的实现构成构成UML图 单例模式的六种实现懒汉式-线程不安全懒汉式-线程安全饿汉式-线程安全双重校验锁-线程安全静态内部类实现枚举实现 总结其他设计模式文章&#xff1a;最后 定义 单例模式是一种创建型设计模式&#xff0c;它用来保证一个类只有一个实…

Candance Allegro 入门教程笔记:PCB封装库的组成元素

文章目录 一、PCB封装库的组成元素二、使用Padstack Edictor制作封装焊盘引脚三、PCB Editor软件创建贴片封装&#xff08;STM32F103T8U6 QFN36 为例&#xff09;1.引入库2.读入数据 一、PCB封装库的组成元素 一般来说&#xff0c;针对于Allegro软件&#xff0c;完整的封装是由…