建委网证书查询/重庆seo教程博客
文章目录
- 6 任务执行
- 6.1 在线程中执行任务
- 6.1.1 串行地执行任务
- 6.1.2 显式地为任务创建线程
- 6.1.3 无限制创建线程的不足
- 6.2 Executor框架
- 6.2.1 示例:基于Executor的Web服务器
- 6.2.2 执行策略
- 6.2.3 线程池
- 6.2.4 Executor的生命周期
- 6.2.5 延迟任务与周期任务
- 6.3 找出可利用的并行性
- 6.3.1 示例:串行的页面渲染器
- 6.3.2 携带结果的任务Callable和Future
- 6.3.3 示例:使用Future实现页面渲染器
- 6.3.4 在异构任务并行化中存在的局限
- 6.3.5 CompletionService:Executor与BlockingQueue
- 6.3.6 使用CompletionService实现页面渲染器
- 6.3.7 为任务设置时间
- 6.3.8 示例:旅行预订门户网站
6 任务执行
6.1 在线程中执行任务
应选择清晰的任务边界以及明确的任务执行策略。
一种自然的任务边界选择方式:以独立的客户请求为边界。
6.1.1 串行地执行任务
6.1.2 显式地为任务创建线程
程序6-1-2-1 在Web服务器中为每一个请求启动一个新的线程(不要这么做)
class ThreadPerTaskWebServer {public static void main(String[] args) throws IOException {ServerSocket socket = new ServerSocket(80);while (true) {final Socket connection = socket.accept();Runnable task = new Runnable() {@Overridepublic void run() {handleRequest(connection);}};new Thread(task).start();}}
}
串行情况下可以提升性能。只要请求的到达速率不超出服务器的请求处理能力。
6.1.3 无限制创建线程的不足
线程生命周期的开销非常高。 线程创建需要时间,延迟处理的请求,并且需要JVM和操作系统提供一些辅助操作。
资源消耗。 活跃线程会消耗系统资源,尤其是内存。大量空闲的线程会占用许多内存,给垃圾收集器带来压力,而且大量线程在竞争CPU资源时还会产生其他的性能开销。如果有足够多的线程使所有的CPU保持忙碌状态,那么再创建更多的线程反而会降低性能。
稳定性。 在一定范围内,增加线程可以提高系统的吞吐率,但是如果超出了这个范围,再创建更多的线程会降低程序的执行速度。如果过多地创建一个线程,那么整个应用程序将崩溃。
6.2 Executor框架
Executor基于生产者-消费者模式,提交任务的操作相当于生产者(生成待完成的工作单元),执行任务的线程相当于消费者(执行完这些工作单元)。
6.2.1 示例:基于Executor的Web服务器
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;class TaskExecutionWebServer {private static final int NTHREADS = 100;private static final Executor exec = Executors.newFixedThreadPool(NTHREADS);public static void main(String[] args) throws IOException {ServerSocket socket = new ServerSocket(80);while (true) {final Socket connection = socket.accept();Runnable task = new Runnable() {@Overridepublic void run() {handleRequest(connection);}};exec.execute(task);}}
}
6.2.2 执行策略
使用线程池来取代new Thread方式。
6.2.3 线程池
- newFixedThreadPool。固定长度的线程池。
- newCachedThreadPool。如果线程池的当前规模超过了处理需求时,那么将回收空闲的线程;而当需求增加时,则可以添加新的线程,线程池的规模不存在任何限制。
- newSingleThreadExecutor。创建单个工作线程来执行任务,如果这个线程异常结束,会创建另一个线程来替代。
- newScheduledThreadPool。固定长度的线程池。以延迟或者定时的方式来执行任务。
6.2.4 Executor的生命周期
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionException;public class LifeCycleWebServer {private final ExecutorService exec = ...;public void start() throws IOException {ServerSocket socket = new ServerSocket(80);while (!exec.isShutdown()) {try {final Socket conn = socket.accept();exec.execute(new Runnable() {@Overridepublic void run() {handleRequest(conn);}});} catch (RejectedExecutionException e) {if (!exec.isShutdown()) {log("task submission rejected", e);}}}}public void stop() {exec.shutdown();}void handleRequest(Socket connection) {Request req = readRequest(connection);if (isShutdownRequest(req)) {stop();} else {dispatchRequest(req);}}
}
6.2.5 延迟任务与周期任务
推荐使用ScheduleThreadPoolExecutor。
Timer存在的问题:
(1)Timer支持基于绝对时间的调度机制,因此任务的执行对系统时钟变化很敏感。ScheduleThreadPoolExecutor只支持基于相对时间的变化。
(2)Timer执行所有的定时任务时只会创建一个线程。如果某个任务的执行时间过长,那么将破坏其他TimerTask的定时精确性。例如某个周期TimerTask需要每10ms执行一次,而另一个需要40ms,那么这个周期任务或者在40ms之后快速连续调用四次,或者彻底丢失4次调用。
(3)Timer线程并不捕获异常。如果TimerTask抛出异常终止了定时任务,timer不会回复线程执行,而是会错误的认为整个Timer都被取消了。 因此,已被调度但尚未执行的TimerTask将不会再执行,新的任务也不会被调度。
程序清单 6-2-5-1 错误的Timer行为
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;public class OutOfTime {public static void main(String[] args) throws Exception {long startTime = System.currentTimeMillis();Timer timer = new Timer();timer.schedule(new ThrowTask(), 1);TimeUnit.SECONDS.sleep(1);long endTime = System.currentTimeMillis();System.out.println(endTime - startTime);timer.schedule(new ThrowTask(), 1);TimeUnit.SECONDS.sleep(5);}static class ThrowTask extends TimerTask {@Overridepublic void run() {throw new RuntimeException();}}
}Exception in thread "Timer-0" java.lang.RuntimeExceptionat executor.OutOfTime$ThrowTask.run(OutOfTime.java:22)at java.base/java.util.TimerThread.mainLoop(Timer.java:566)at java.base/java.util.TimerThread.run(Timer.java:516)
1002
Exception in thread "main" java.lang.IllegalStateException: Timer already cancelled.at java.base/java.util.Timer.sched(Timer.java:409)at java.base/java.util.Timer.schedule(Timer.java:205)at executor.OutOfTime.main(OutOfTime.java:15)
程序一秒钟就结束了,并抛出了异常。
在Java5.0或者更高的JDK中,将很少使用Timer。
6.3 找出可利用的并行性
6.3.1 示例:串行的页面渲染器
import java.util.ArrayList;
import java.util.List;public class SingleThreadRender {void renderPage(CharSequence source) {renderText(source);List<ImageData> imageData = new ArrayList<>();for (ImageInfo imageInfo : scanForImageInfo(source)) {imageData.add(imageInfo.downloadImage());}for (ImageData data : imageData) {renderImage(data);}}
}
6.3.2 携带结果的任务Callable和Future
6.3.3 示例:使用Future实现页面渲染器
程序清单6-3-3-1 使用Future等待图像下载
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;public class FutureRender {private final ExecutorService executor = ...;void renderPage(CharSequence source) {final List<ImageInfo> imageInfos = scanForImageInfo(source);Callable<List<ImageData>> task = new Callable<List<ImageData>>() {@Overridepublic List<ImageData> call() throws Exception {List<ImageData> result = new ArrayList<>();for (ImageInfo imageInfo : imageInfos) {result.add(imageInfo.downloadImage());}return result;}};Future<List<ImageData>> future = executor.submit(task);renderText(source);try {List<ImageData> imageDataList = future.get();for (ImageData imageData : imageDataList) {renderImage(imageData);}} catch (InterruptedException e) {// 重新设置线程的中断状态Thread.currentThread().interrupt();// 由于不需要结果,因此取消任务future.cancel(true);} catch (ExecutionException e) {throw launcherThrowable(e.getCause());}}}
6.3.4 在异构任务并行化中存在的局限
只有大量相互独立且同构的任务可以并发进行处理时,才能体现出将程序的工作负载分配到多个任务中带来的真正性能提升。
6.3.5 CompletionService:Executor与BlockingQueue
6.3.6 使用CompletionService实现页面渲染器
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;public class Render {private final ExecutorService excutor;Render(ExecutorService excutor) {this.excutor = excutor;}void renderPage(CharSequence source) {List<ImageInfo> info = scanForImageInfo(source);CompletionService<ImageData> completionService = new ExecutorCompletionService<>(excutor);for (final ImageInfo imageInfo: info) {completionService.submit(new Callable<ImageData>() {@Overridepublic ImageData call() throws Exception {return imageInfo.downloadImage();}});}renderText(source);try {for (int t = 0, n = info.size(); t < n; t++) {Future<ImageData> f = completionService.take();ImageData imageData = f.get();renderImage(imageData);}} catch (InterruptedException e) {Thread.currentThread().interrupt();} catch (ExecutionException e) {throw launcherThrowable(e.getCause());}}
}
6.3.7 为任务设置时间
Page renderPageWithAd() throws InterruptedException {long endNanos = System.nanoTime() + END_BUDGET;Future<Ad> f = excutor.submit(new FetchAdTask());// 在等待广告的同时显示页面。Page page = renderPageBody();Ad ad;try {long timeLeft = endNanos - System.nanoTime();ad = f.get(timeLeft, TimeUnit.NANOSECONDS);} catch (ExecutionException e) {ad = DEFAULT_AD;} catch (TimeoutException e) {ad = DEFAULT_AD;f.cancel(true);}page.setAd(ad);return page;}
6.3.8 示例:旅行预订门户网站
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;private class QuoteTask implements Callable<TravelQuote> {private final TravelCompany company;private final TravelInfo travelInfo;@Overridepublic TravelQuote call() throws Exception {return company.solicitQuote(travelInfo);}
}public List<TravelQuote> getRankedTravelQuotes(TravelInfo travelInfo, Set<TravelCompany> companies,Comparator<TravelQuote> ranking, long time, TimeUnit unit) throws InterruptedException {List<QuoteTask> tasks = new ArrayList<>();for (TravelCompany company : companies) {tasks.add(new QuoteTask(company, travelInfo));}List<Future<TravelQuote>> futures = exec.invokeAll(tasks, time, unit);List<TravelQuote> quotes = new ArrayList<>(futures.size());Iterator<QuoteTask> iterator = tasks.iterator();for (Future<TravelQuote> f : futures) {QuoteTask task = iterator.next();try {quotes.add(f.get());} catch (ExecutionException e) {quotes.add(task.getFailureQuote(e.getCause()));} catch (CancellationException e) {quotes.add(task.getTimeoutQuote(e.getCause()));}}Collections.sort(quotes, ranking);return quotes;
}
相关文章:

Java并发编程实战——结构化并发应用程序
文章目录 6 任务执行6.1 在线程中执行任务6.1.1 串行地执行任务6.1.2 显式地为任务创建线程6.1.3 无限制创建线程的不足 6.2 Executor框架6.2.1 示例:基于Executor的Web服务器6.2.2 执行策略6.2.3 线程池6.2.4 Executor的生命周期6.2.5 延迟任务与周期任务 6.3 找出…...

uniapp echarts 点击失效
这个问题网上搜了一堆,有的让你降版本,有的让你改源码。。。都不太符合预期,目前我的方法可以用最新的echarts。 这个方法就是由npm安装转为CDN,当然你可能会质疑用CDN这样会不稳定,那如果CDN的地址是本地呢࿱…...

手机开启应急预警通知 / 地震预警
前言 安卓手机在检测到地震时,将发送地震预警通知,但此设置是默认关闭的,原因是以防引发用户恐慌从而引发安全问题,且开启此设置需要完成指引教程,因此默认关闭此设置。下文介绍如何开启此设置。 开启方法 华为手机开…...

2020年12月 Python(一级)真题解析#中国电子学会#全国青少年软件编程等级考试
一、单选题(共25题,每题2分,共50分) 第1题 执行语句print(10==10.0)的结果为? A:10 B:10.0 C:True D:False 正确的答案是 C:True。 解析:在Python中,比较运算符 “==” 用于比较两个值是否相等。在这个特定的比较中,整数10和浮点数10.0在数值上是相等的。…...

遇到无法复现的 Bug
当我们在软件开发过程中遇到无法复现的 Bug 时,这可能会让我们感到头疼和困惑。处理这种 Bug 需要一些技巧和方法来帮助我们更好地解决问题。本篇博客将为大家总结一些常用的技术手段和策略,希望能对开发者们在日常工作中遇到类似问题时提供一些帮助。 …...

虚拟列表的实现(简单易懂)
起因: app开发过程中遇到需要渲染3000行的列表,页面直接卡顿,所以开始研究起虚拟列表 实现前提条件: item项等高列表 实现思路: 首先是dom结构: 定义一个容器(固定高度)&#…...

【WordPress】如何在WordPress中实现真·页面路由
这篇文章也可以在我的博客中查看 页面路由 是什么 页面路由是指从url顺着网线砍到网站内容的途径,说人话就是地址与页面的映射。 就像真实世界的地址一样,我要找你,必须知道你的地址。 在网站中,通过地址找内容的机制…...

Android界面设计与用户体验
Android界面设计与用户体验 1. 引言 在如今竞争激烈的移动应用市场,提供优秀的用户体验成为了应用开发的关键要素。无论应用功能多么强大,如果用户界面设计不合理,用户体验不佳,很可能会导致用户流失。因此,在Androi…...

基于 FFmpeg 的跨平台视频播放器简明教程(八):音画同步
系列文章目录 基于 FFmpeg 的跨平台视频播放器简明教程(一):FFMPEG Conan 环境集成基于 FFmpeg 的跨平台视频播放器简明教程(二):基础知识和解封装(demux)基于 FFmpeg 的跨平台视频…...

【NLP pytorch】基于BiLSTM-CRF模型医疗数据实体识别实战(项目详解)
基于BiLSTM-CRF模型医疗数据实体识别实战 1数据来源与加载1.1 数据来源1.2 数据类别名称和定义1.3 数据介绍2 模型介绍2 数据预处理2.1 数据读取2.2 数据标注2.3 数据集划分2.4 词表和标签的生成3 Dataset和DataLoader3.1 Dataset3.2 DataLoader4 BiLSTM模型定义5 CRF模型6 模型…...

人工智能原理(1)
*请注意,本文仅供学习使用* 目录 一、人工智能发展 1、孕育期 2、摇篮期 3、形成期 4、发展期(1970-1979) 5、实用期 6、稳步发展期 二、何为人工智能 1、智能的主要观点 2、智能定义 3、人工智能定义 三、人工智能研究方法 1、…...

预测成真,国内传来三个消息,中国年轻人变了,创新力产品崛起
中国的年轻人真的变了! 最近,国内传来三个消息,让外媒的预测成真。 第一,奥迪要开始用国产车的平台了。这里需要说明的是新能源汽车,奥迪也曾多次公开表示,承认了当前中国新能源汽车核心技术上的领先。 第…...

维深(Wellsenn):2023中国消费端VR内容开发商调研报告(附下载
关于报告的所有内容,公众【营销人星球】获取下载查看 核心观点 国内互联网大厂商入局VR,字节跳动、网易表态明确。字节跳动2021年收购国内头部VR硬件厂商PICO后,加速构建VR内容生态,2021年 成立海南创见未来当前已推出VR视频应用…...

redis事务管理详解
事务管理 事务管理乐观锁与悲观锁watch命令实现乐观锁watch命令示例 事务管理 Redis 提供了事务管理功能,可以通过 Redis 的 MULTI、EXEC、WATCH 和 DISCARD 命令来实现。 开启事务: 使用 MULTI 命令开始一个事务,表示接下来执行的命令都属于…...

国产低功耗蓝牙HS6621CxC/6621Px系列支持Find My网络功能方案芯片
目录 什么是“Find My“?HS6621系列简介 什么是“Find My“? “Find My”是苹果公司于19年前推出的针对失物追踪,Find My iPhone(查找我的iPhone)和Find My Friends(查找朋友)的结合体应用。为…...

【openGauss】分区表的介绍与使用
一、openGauss分区表介绍 在openGauss中,数据分区是在一个节点内部对数据按照用户指定的策略做进一步的水平分表,将表中的数据按照指定方式划分为多个互不重叠的部分。 对于大多数用户使用场景,分区表和普通表相比具有以下优点: …...

代码随想录算法训练营day57
文章目录 Day57回文子串题目思路代码 最长回文子序列题目思路代码 Day57 回文子串 647. 回文子串 - 力扣(LeetCode) 题目 给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。…...

【基础类】—前后端通信类系统性学习
一、什么是同源策略及限制 同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。源:协议、域名和端口, 默认端口是80 三者有一个不同,即源不同,就是跨域 ht…...

vite项目中使用@代表根路径
1.配置vite.config.ts import { defineConfig } from vite import vue from vitejs/plugin-vue import path from pathexport default defineConfig({plugins: [vue()],resolve: {alias:{: path.resolve(__dirname, src) }} })2.报错path和__dirname 找不到模块“path”或其相…...

冶金化工操作VR虚拟仿真实验软件提高员工们协同作业的配合度
对于高风险行业来说,开展安全教育培训是企业的重点工作,传统培训逐渐跟不上时代变化和工人需求,冶金安全VR模拟仿真培训系统作为一种新型的教育和培训工具,借助VR虚拟现实技术为冶金行业的工人提供一个安全、高效的培训环境。 冶金…...

SQL Server数据库 -- 索引与视图
文章目录 一、索引 聚集索引非聚集索引二、视图三、自定义函数 标量函数表值函数四、游标五、总结 前言 在学习完创建库表、查询等知识点后,为了更加方便优化数据库的存储和内容,我们需要学习一系列的方法例如索引与视图等等,从而使我们更加…...

2023 java web面试秘籍
目录 第一章:Java Web基础知识1.介绍3.Java Web基本概念 4.常见面试问题第二章:Java Web核心概念和技术1.介绍3.Servlet和JSP4.Web安全5.常见面试问题 第三章:Java Web高级概念和技术1.介绍3.Spring框架4.安全性5.常见面试问题 第四章&#x…...

2023-08-05力扣今日二题
链接: 剑指 Offer 18. 删除链表的节点 题意: 如题 解: 基础链表操作 实际代码: #include<iostream> using namespace std; struct ListNode {int val;ListNode *next;ListNode(int x) : val(x), next(NULL) {} }; Li…...

stl_list类(使用+实现)(C++)
list 一、list-简单介绍二、list的常用接口1.常见构造2.iterator的使用3.Capacity和Element access4.Modifiers5.list的迭代器失效 三、list实现四、vector 和 list 对比五、迭代器1.迭代器的实现2.迭代器的分类(按照功能分类)3.反向迭代器(1)、包装逻辑…...

利用hfish反控境外攻击源主机
导师给了7个网络安全课题选题,本想和他聊了下思路,他一挥手让我先做出点东西再来聊就把我打发走了…… 正好前段时间阿里云到校做推广,用优惠卷薅了一台云服务器,装了hfish先看下情况 没想到才装上没两天数据库就爆了࿰…...

4、Rocketmq之存储原理
CommitLog ~ MappedFileQueue ~ MappedFile集合...

在线原型设计工具有好用的吗?就是这10个
随着设计工作的不断发展,原型设计在设计工作中越来越重要,而在线原型设计工具在减轻了设计师工作负担的同时也提高了设计师的工作效率,今天本文将为大家推荐10个能在线使用的原型设计工具,一起来看看吧! 1、即时设计 …...

Vc - Qt - QPainter translate
QPainter的translate()函数是用来对绘制坐标系统进行平移操作的方法。它可以将绘制的原点(坐标轴的起始点)在水平和垂直方向上进行平移。以下是一个使用QPainter的translate()方法进行坐标平移的示例代码: QPainter painter(this);// 绘制一个…...

Spark Catalog详解
前言 旁边的实习生说:我想要用spark代码中对hive库中的内部表和外部表进行批量删除(包括数据),咋感觉网上搜了一圈都找不到解决方案啊,spark这么鸡肋吗? 我:你应该静下心来好好把spark基础知识进行全面学习。 实习生:难道spark有这功能,而我没有学习过?咋弄啊? 我:…...

【Spring专题】手写简易Spring容器过程分析
前置知识 《【Spring专题】Spring底层核心原理解析》 思路整理 我们在上一节《【Spring专题】Spring底层核心原理解析》课里面有简单分析过一个Spring容器的一般流程,所以,本节课我们这里尝试写一下简易的Spring容器。 手写源码示例 一、手写前的准…...