C++项目实战-实际应用

2023-11-15

目录

典型IO的两个阶段(网络IO)

Linux上的五种IO模型

1.阻塞 blocking

2.非阻塞

3.IO复用

4.信号驱动

5.异步

Web Server

 HTTP协议(应用层的协议)

简介

概述

工作原理

HTTP 请求报文格式

HTTP响应报文格式 

HTTP请求方法 

HTTP状态码

服务器编程基本框架 

 两种高效的事件处理模式

Reactor模式

Proactor模式 

模拟 Proactor 模式 

线程池 

有限状态机 

EPOLLONESHOT事件

服务器压力测试


典型IO的两个阶段(网络IO)

I和O分别表示输入、输出。网络通信是通过网络套接字socket实现是,其实就是内核中的一个缓冲区。

网络IO分为两个阶段:数据就绪、数据读写(这两个概念是不同的,不能混为一潭)

数据准备:根据系统IO操作的就绪状态

        分为:阻塞、非阻塞

数据读写:根据内核与应用程序的交互方式

        分为:同步、异步

在处理IO的时候,阻塞和非阻塞都是同步的,只有调用了特殊的API才是异步的

总结:

        一个经典的网络IO分为两个阶段:数据就绪、数据读写。数据就绪分为阻塞和非阻塞。阻塞是调用IO方法是线程进入阻塞状态(当数据没到达不返回,阻塞等待数据到达),非阻塞(数据没有到达任然返回,通过返回值来判断)不会改变线程的状态,通过返回值进行判断。不管是read还是recv,如果返回值为 -1会根据返回状态判断时候为缓冲区中没有数据和是否被信号软中断,是否重新调用。

        数据读写分为同步和异步,我们知道socket是在内核中的的缓冲区,同步的意思就是应用程序来从内核中读取数据,此时应用程序工作的内容是从内核读数据,没有做其他事情。而异步是让内核来帮我们完成数据读写的操作,当数据读写完成,通过一种通知方式来告诉应用程序,这样的话,应用程序可以干其他事情,当数据读写完成后再来处理读写的数据就可以了,一般我们需要通过文件描述符(socket)、buf(装数据的容器)、通知方式(sigio信号)。异步的方式通过特殊的API调用,aio_read   aio_write

        同步的方式相比异步的方式效率较低一点,异步的方式实现起来比较复杂

Linux上的五种IO模型

1.阻塞 blocking

调用者调用了某个函数,等待这个函数返回,期间什么也不做,不停的去检查这个函数有没有返回,必 须等这个函数返回才能进行下一步动作

线程(或进程)处于阻塞状态不消耗CPU,但是线程(进程)不能干其他事情 

2.非阻塞

非阻塞等待,每隔一段时间就去检测IO事件是否就绪。没有就绪就可以做其他事。非阻塞I/O执行系统调 用总是立即返回,不管事件是否已经发生,若事件没有发生,则返回-1,此时可以根据 errno 区分这两 种情况,对于accept,recv 和 send,事件未发生时,errno 通常被设置成 EAGAIN。

一般采用while轮询的方式,当缓冲没有数据到达,可以干其他事情。比较消耗系统资源。通过fcntl可以设置非阻塞。比如:有10000个客户端要发送数据,每一次循环将有10000次系统调用。 

3.IO复用

Linux 用 select/poll/epoll 函数实现 IO 复用模型,这些函数也会使进程阻塞,但是和阻塞IO所不同的是 这些函数可以同时阻塞多个IO操作。而且可以同时对多个读操作、写操作的IO函数进行检测。直到有数 据可读或可写时,才真正调用IO操作函数。

可以同时检测多个IO,一般交给内核来完成监测工作,当有数据到达时,就通过应用程序调用read进行数据读写。可以理解为是非阻塞、忙轮询方式的一种改进。在一个线程或进程中可以同时检测多个客户端

4.信号驱动

Linux 用套接口进行信号驱动 IO,安装一个信号处理函数,进程继续运行并不阻塞,当IO事件就绪,进 程收到SIGIO 信号,然后处理 IO 事件。

通过sigio信号来处理,当数据准备好之后,发送该信号,然后捕捉该信号并调用read进行数据读写 。

内核在第一个阶段是异步,在第二个阶段是同步;与非阻塞IO的区别在于它提供了消息通知机制,不需 要用户进程不断的轮询检查,减少了系统API的调用次数,提高了效率。

5.异步

Linux中,可以调用 aio_read 函数告诉内核描述字缓冲区指针和缓冲区的大小、文件偏移及通知的方 式,然后立即返回,当内核将数据拷贝到缓冲区后,再通知应用程序。

 内核完成监听和读写操作,当数据读写完成,通知应用程序处理数据。

/* Asynchronous I/O control block. */
struct aiocb
{
int aio_fildes; /* File desriptor. */
int aio_lio_opcode; /* Operation to be performed. */
int aio_reqprio; /* Request priority offset. */
volatile void *aio_buf; /* Location of buffer. */
size_t aio_nbytes; /* Length of transfer. */
struct sigevent aio_sigevent; /* Signal number and value. */
/* Internal members. */
struct aiocb *__next_prio;
int __abs_prio;
int __policy;
int __error_code;
__ssize_t __return_value;
#ifndef __USE_FILE_OFFSET64
__off_t aio_offset; /* File offset. */
char __pad[sizeof (__off64_t) - sizeof (__off_t)];
#else
__off64_t aio_offset; /* File offset. */
#endif
char __glibc_reserved[32];
};

Web Server

一个 Web Server 就是一个服务器软件(程序),或者是运行这个服务器软件的硬件(计算机)。其主 要功能是通过 HTTP 协议与客户端(通常是浏览器(Browser))进行通信,来接收,存储,处理来自 客户端的 HTTP 请求,并对其请求做出 HTTP 响应,返回给客户端其请求的内容(文件、网页等)或返 回一个 Error 信息。

 

 HTTP协议(应用层的协议)

GoWeb开发讲解_干饭小白的博客-CSDN博客_go web开发

简介

超文本传输协议(Hypertext Transfer Protocol,HTTP)是一个简单的请求 - 响应协议,它通常运行在 TCP 之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。请求和响应消息的 头以 ASCII 形式给出;而消息内容则具有一个类似 MIME 的格式。HTTP是万维网的数据通信的基础。 HTTP的发展是由蒂姆·伯纳斯-李于1989年在欧洲核子研究组织(CERN)所发起。HTTP的标准制定由万 维网协会(World Wide Web Consortium,W3C)和互联网工程任务组(Internet Engineering Task Force,IETF)进行协调,最终发布了一系列的RFC,其中最著名的是1999年6月公布的 RFC 2616,定 义了HTTP协议中现今广泛使用的一个版本——HTTP 1.1。

概述

HTTP 是一个客户端终端(用户)和服务器端(网站)请求和应答的标准(TCP)。通过使用网页浏览 器、网络爬虫或者其它的工具,客户端发起一个HTTP请求到服务器上指定端口(默认端口为80)。我们 称这个客户端为用户代理程序(user agent)。应答的服务器上存储着一些资源,比如 HTML 文件和图 像。我们称这个应答服务器为源服务器(origin server)。在用户代理和源服务器中间可能存在多个“中 间层”,比如代理服务器、网关或者隧道(tunnel)。 尽管 TCP/IP 协议是互联网上最流行的应用,HTTP 协议中,并没有规定必须使用它或它支持的层。事实 上,HTTP可以在任何互联网协议上,或其他网络上实现。HTTP 假定其下层协议提供可靠的传输。因此,任何能够提供这种保证的协议都可以被其使用。因此也就是其在 TCP/IP 协议族使用 TCP 作为其传 输层。 通常,由HTTP客户端发起一个请求,创建一个到服务器指定端口(默认是80端口)的 TCP 连接。HTTP 服务器则在那个端口监听客户端的请求。一旦收到请求,服务器会向客户端返回一个状态,比 如"HTTP/1.1 200 OK",以及返回的内容,如请求的文件、错误消息、或者其它信息。

工作原理

HTTP 协议定义 Web 客户端如何从 Web 服务器请求 Web 页面,以及服务器如何把 Web 页面传送给客 户端。HTTP 协议采用了请求/响应模型。客户端向服务器发送一个请求报文,请求报文包含请求的方 法、URL、协议版本、请求头部和请求数据。服务器以一个状态行作为响应,响应的内容包括协议的版 本、成功或者错误代码、服务器信息、响应头部和响应数据。

以下是 HTTP 请求/响应的步骤: 1. 客户端连接到 Web 服务器 一个HTTP客户端,通常是浏览器,与 Web 服务器的 HTTP 端口(默认为 80 )建立一个 TCP 套接 字连接。例如,http://www.baidu.com。(URL) 2. 发送 HTTP 请求 通过 TCP 套接字,客户端向 Web 服务器发送一个文本的请求报文,一个请求报文由请求行、请求 头部、空行和请求数据 4 部分组成。 3. 服务器接受请求并返回 HTTP 响应 Web 服务器解析请求,定位请求资源。服务器将资源复本写到 TCP 套接字,由客户端读取。一个 响应由状态行、响应头部、空行和响应数据 4 部分组成。 4. 释放连接 TCP 连接 若 connection 模式为 close,则服务器主动关闭 TCP连接,客户端被动关闭连接,释放 TCP 连 接;若connection 模式为 keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求; 5. 客户端浏览器解析 HTML 内容 客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应 头告知以下为若干字节的 HTML 文档和文档的字符集。客户端浏览器读取响应数据 HTML,根据 HTML 的语法对其进行格式化,并在浏览器窗口中显示。

HTTP 请求报文格式

 

HTTP响应报文格式 

 

HTTP请求方法 

HTTP/1.1 协议中共定义了八种方法(也叫“动作”)来以不同方式操作指定的资源: 1. GET:向指定的资源发出“显示”请求。使用 GET 方法应该只用在读取数据,而不应当被用于产生“副 作用”的操作中,例如在 Web Application 中。其中一个原因是 GET 可能会被网络蜘蛛等随意访 问。 2. HEAD:与 GET 方法一样,都是向服务器发出指定资源的请求。只不过服务器将不传回资源的本文 部分。它的好处在于,使用这个方法可以在不必传输全部内容的情况下,就可以获取其中“关于该 资源的信息”(元信息或称元数据)。 3. POST:向指定资源提交数据,请求服务器进行处理(例如提交表单或者上传文件)。数据被包含 在请求本文中。这个请求可能会创建新的资源或修改现有资源,或二者皆有。 4. PUT:向指定资源位置上传其最新内容。 5. DELETE:请求服务器删除 Request-URI 所标识的资源。 6. TRACE:回显服务器收到的请求,主要用于测试或诊断。 7. OPTIONS:这个方法可使服务器传回该资源所支持的所有 HTTP 请求方法。用'*'来代替资源名称, 向 Web 服务器发送 OPTIONS 请求,可以测试服务器功能是否正常运作。 8. CONNECT:HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。通常用于SSL加密服 务器的链接(经由非加密的 HTTP 代理服务器)。

HTTP状态码

所有HTTP响应的第一行都是状态行,依次是当前HTTP版本号,3位数字组成的状态代码,以及描述状态 的短语,彼此由空格分隔。

状态代码的第一个数字代表当前响应的类型:

1xx消息——请求已被服务器接收,继续处理

2xx成功——请求已成功被服务器接收、理解、并接受

3xx重定向——需要后续操作才能完成这一请求

4xx请求错误——请求含有词法错误或者无法被执行

5xx服务器错误——服务器在处理某个正确请求时发生错误

虽然 RFC 2616 中已经推荐了描述状态的短语,例如"200 OK","404 Not Found",但是WEB开发者仍 然能够自行决定采用何种短语,用以显示本地化的状态描述或者自定义信息。

服务器编程基本框架 

虽然服务器程序种类繁多,但其基本框架都一样,不同之处在于逻辑处理

I/O 处理单元是服务器管理客户连接的模块。它通常要完成以下工作:等待并接受新的客户连接,接收 客户数据,将服务器响应数据返回给客户端。但是数据的收发不一定在 I/O 处理单元中执行,也可能在 逻辑单元中执行,具体在何处执行取决于事件处理模式。 一个逻辑单元通常是一个进程或线程。它分析并处理客户数据,然后将结果传递给 I/O 处理单元或者直 接发送给客户端(具体使用哪种方式取决于事件处理模式)。服务器通常拥有多个逻辑单元,以实现对 多个客户任务的并发处理。 网络存储单元可以是数据库、缓存和文件,但不是必须的。 请求队列是各单元之间的通信方式的抽象。I/O 处理单元接收到客户请求时,需要以某种方式通知一个 逻辑单元来处理该请求。同样,多个逻辑单元同时访问一个存储单元时,也需要采用某种机制来协调处 理竞态条件。请求队列通常被实现为池的一部分。 

 两种高效的事件处理模式

服务器程序通常需要处理三类事件:I/O 事件、信号及定时事件。有两种高效的事件处理模式:Reactor 和 Proactor同步 I/O 模型通常用于实现 Reactor 模式,异步 I/O 模型通常用于实现 Proactor 模式。

Reactor模式

要求主线程(I/O处理单元)只负责监听文件描述符上是否有事件发生,有的话就立即将该事件通知工作 线程(逻辑单元),将 socket 可读可写事件放入请求队列,交给工作线程处理。除此之外,主线程不做 任何其他实质性的工作。读写数据,接受新的连接,以及处理客户请求均在工作线程中完成。

使用同步 I/O(以 epoll_wait 为例)实现的 Reactor 模式的工作流程是:

1. 主线程往 epoll 内核事件表中注册 socket 上的读就绪事件。

2. 主线程调用 epoll_wait 等待 socket 上有数据可读。

3. 当 socket 上有数据可读时, epoll_wait 通知主线程。主线程则将 socket 可读事件放入请求队列。

4. 睡眠在请求队列上的某个工作线程被唤醒,它从 socket 读取数据,并处理客户请求,然后往 epoll 内核事件表中注册该 socket 上的写就绪事件。

5. 当主线程调用 epoll_wait 等待 socket 可写。

6. 当 socket 可写时,epoll_wait 通知主线程。主线程将 socket 可写事件放入请求队列。

7. 睡眠在请求队列上的某个工作线程被唤醒,它往 socket 上写入服务器处理客户请求的结果。 Reactor 模式的工作流程:

Proactor模式 

Proactor 模式将所有 I/O 操作都交给主线程和内核来处理(进行读、写),工作线程仅仅负责业务逻辑。

使用异步 I/O 模型(以 aio_read 和 aio_write 为例)实现的 Proactor 模式的工作流程是:

1. 主线程调用 aio_read 函数向内核注册 socket 上的读完成事件,并告诉内核用户读缓冲区的位置, 以及读操作完成时如何通知应用程序(这里以信号为例)。

2. 主线程继续处理其他逻辑。

3. 当 socket 上的数据被读入用户缓冲区后,内核将向应用程序发送一个信号,以通知应用程序数据 已经可用。

4. 应用程序预先定义好的信号处理函数选择一个工作线程来处理客户请求。工作线程处理完客户请求 后,调用 aio_write 函数向内核注册 socket 上的写完成事件,并告诉内核用户写缓冲区的位置,以 及写操作完成时如何通知应用程序。

5. 主线程继续处理其他逻辑。

6. 当用户缓冲区的数据被写入 socket 之后,内核将向应用程序发送一个信号,以通知应用程序数据 已经发送完毕。

7. 应用程序预先定义好的信号处理函数选择一个工作线程来做善后处理,比如决定是否关闭 socket。

Proactor 模式的工作流程:

模拟 Proactor 模式 

使用同步 I/O 方式模拟出 Proactor 模式。原理是:主线程执行数据读写操作,读写完成之后,主线程向 工作线程通知这一”完成事件“。那么从工作线程的角度来看,它们就直接获得了数据读写的结果,接下 来要做的只是对读写的结果进行逻辑处理。

使用同步 I/O 模型(以 epoll_wait为例)模拟出的 Proactor 模式的工作流程如下:

1. 主线程往 epoll 内核事件表中注册 socket 上的读就绪事件。

2. 主线程调用 epoll_wait 等待 socket 上有数据可读。

3. 当 socket 上有数据可读时,epoll_wait 通知主线程。主线程从 socket 循环读取数据,直到没有更 多数据可读,然后将读取到的数据封装成一个请求对象并插入请求队列。

4. 睡眠在请求队列上的某个工作线程被唤醒,它获得请求对象并处理客户请求,然后往 epoll 内核事 件表中注册 socket 上的写就绪事件。

5. 主线程调用 epoll_wait 等待 socket 可写。

6. 当 socket 可写时,epoll_wait 通知主线程。主线程往 socket 上写入服务器处理客户请求的结果。

 

线程池 

线程池是由服务器预先创建的一组子线程,线程池中的线程数量应该和 CPU 数量差不多。线程池中的所 有子线程都运行着相同的代码。当有新的任务到来时,主线程将通过某种方式选择线程池中的某一个子 线程来为之服务。相比与动态的创建子线程,选择一个已经存在的子线程的代价显然要小得多。

至于主线程选择哪个子线程来为新任务服务,则有多种方式:

主线程使用某种算法来主动选择子线程。最简单、最常用的算法是随机算法和 Round Robin(轮流 选取)算法,但更优秀、更智能的算法将使任务在各个工作线程中更均匀地分配,从而减轻服务器 的整体压力。 主线程和所有子线程通过一个共享的工作队列来同步,子线程都睡眠在该工作队列上。当有新的任 务到来时,主线程将任务添加到工作队列中。这将唤醒正在等待任务的子线程,不过只有一个子线 程将获得新任务的”接管权“,它可以从工作队列中取出任务并执行之,而其他子线程将继续睡眠在 工作队列上。

线程池的一般模型为:

线程池中的线程数量最直接的限制因素是中央处理器(CPU)的处理器(processors/cores)的数量 N :如果你的CPU是4-cores的,对于CPU密集型的任务(如视频剪辑等消耗CPU计算资源的任务)来 说,那线程池中的线程数量最好也设置为4(或者+1防止其他因素造成的线程阻塞);对于IO密集 型的任务,一般要多于CPU的核数,因为线程间竞争的不是CPU的计算资源而是IO,IO的处理一 般较慢,多于cores数的线程将为CPU争取更多的任务,不至在线程处理IO的过程造成CPU空闲导 致资源浪费。

空间换时间,浪费服务器的硬件资源,换取运行效率。 池是一组资源的集合,这组资源在服务器启动之初就被完全创建好并初始化,这称为静态资源。 当服务器进入正式运行阶段,开始处理客户请求的时候,如果它需要相关的资源,可以直接从池中 获取,无需动态分配。 当服务器处理完一个客户连接后,可以把相关的资源放回池中,无需执行系统调用释放资源。 

有限状态机 

逻辑单元内部的一种高效编程方法:有限状态机(finite state machine)。 有的应用层协议头部包含数据包类型字段,每种类型可以映射为逻辑单元的一种执行状态,服务器可以 根据它来编写相应的处理逻辑。如下是一种状态独立的有限状态机:

STATE_MACHINE( Package _pack )
{
PackageType _type = _pack.GetType();
switch( _type )
{
case type_A:
process_package_A( _pack );
break;
case type_B:
process_package_B( _pack );
break;
}
}

这是一个简单的有限状态机,只不过该状态机的每个状态都是相互独立的,即状态之间没有相互转移。 状态之间的转移是需要状态机内部驱动,如下代码:

STATE_MACHINE()
{
State cur_State = type_A;

while( cur_State != type_C )
{
Package _pack = getNewPackage();
switch( cur_State )
{
case type_A:
process_package_state_A( _pack );
cur_State = type_B;
break;
case type_B:
process_package_state_B( _pack );
cur_State = type_C;
break;
}
}
}

该状态机包含三种状态:type_A、type_B 和 type_C,其中 type_A 是状态机的开始状态,type_C 是状 态机的结束状态。状态机的当前状态记录在 cur_State 变量中。在一趟循环过程中,状态机先通过 getNewPackage 方法获得一个新的数据包,然后根据 cur_State 变量的值判断如何处理该数据包。数据 包处理完之后,状态机通过给 cur_State 变量传递目标状态值来实现状态转移。那么当状态机进入下一 趟循环时,它将执行新的状态对应的逻辑。

EPOLLONESHOT事件

即使可以使用 ET 模式,一个socket 上的某个事件还是可能被触发多次。这在并发程序中就会引起一个 问题。比如一个线程在读取完某个 socket 上的数据后开始处理这些数据,而在数据的处理过程中该 socket 上又有新数据可读(EPOLLIN 再次被触发),此时另外一个线程被唤醒来读取这些新的数据。于 是就出现了两个线程同时操作一个 socket 的局面。一个socket连接在任一时刻都只被一个线程处理,可 以使用 epoll 的 EPOLLONESHOT 事件实现。 对于注册了 EPOLLONESHOT 事件的文件描述符,操作系统最多触发其上注册的一个可读、可写或者异 常事件,且只触发一次,除非我们使用 epoll_ctl 函数重置该文件描述符上注册的 EPOLLONESHOT 事 件。这样,当一个线程在处理某个 socket 时,其他线程是不可能有机会操作该 socket 的。但反过来思 考,注册了 EPOLLONESHOT 事件的 socket 一旦被某个线程处理完毕, 该线程就应该立即重置这个 socket 上的 EPOLLONESHOT 事件,以确保这个 socket 下一次可读时,其 EPOLLIN 事件能被触发,进 而让其他工作线程有机会继续处理这个 socket。 

服务器压力测试

Webbench 是 Linux 上一款知名的、优秀的 web 性能压力测试工具。它是由Lionbridge公司开发。 测试处在相同硬件上,不同服务的性能以及不同硬件上同一个服务的运行状况。 展示服务器的两项内容:每秒钟响应请求数和每秒钟传输数据量。

基本原理:Webbench 首先 fork 出多个子进程,每个子进程都循环做 web 访问测试。子进程把访问的 结果通过pipe 告诉父进程,父进程做最终的统计结果。

测试演示:

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++项目实战-实际应用 的相关文章

  • 如何在测试套件中定义 JUnit 方法规则?

    我有一个类 它是 JUnit 测试类的 JUnit 套件 我想定义一个规则on the suite 这是可以做到的 但需要做一些工作 您还需要定义自己的 Suite 运行程序和测试运行程序 然后在测试运行程序中重写 runChild 使用以
  • Spring控制器是线程安全的吗

    我遇到了这个控制器示例 想知道它是否是线程安全的 我特别想知道 gson 实例变量 import org springframework stereotype Controller import org springframework we
  • Android - 如何访问 onResume 中 onCreate 中实例化的 View 对象?

    In my onCreate 方法 我正在实例化一个ImageButton View public void onCreate Bundle savedInstanceState super onCreate savedInstanceSt
  • 如何在 Eclipse 中用阿拉伯语读写

    我在 eclipse 中编写了这段代码来获取一些阿拉伯语单词 然后打印它们 public class getString public static void main String args throws Exception PrintS
  • Google Inbox 类似 RecyclerView 项目打开动画

    目前 我正在尝试实现 Google Inbox 例如RecyclerView行为 我对电子邮件打开动画很好奇 我的问题是 该怎么做 我的意思是 他们使用了哪种方法 他们用过吗ItemAnimator dispatchChangeStarti
  • 方法断点可能会大大减慢调试速度

    每当向方法声明行添加断点 在 Intellij IDEA 或 Android Studio 中 时 都会出现一个弹出窗口 方法断点可能会大大减慢调试速度 为什么会这样戏剧性地减慢调试速度 是我的问题吗 将断点放在函数的第一行有什么不同 Th
  • Java 变量的作用域

    我不明白为什么这段代码的输出是10 package uno public class A int x 10 A int x 12 new B public static void main String args int x 11 new
  • 使用 Java 在浏览器中下载 CSV 文件

    我正在尝试在 Web 应用程序上添加一个按钮 单击该按钮会下载一个 CSV 文件 该文件很小 大小仅约 4KB 我已经制作了按钮并附加了一个侦听器 文件也准备好了 我现在唯一需要做的就是创建单击按钮时下载 csv 文件的实际事件 假设 fi
  • 为什么我在 Mac 上看到“java.lang.reflect.InaccessibleObjectException: Unable to make private java.nio.DirectByteBuffer(long,int)accessibl

    我已经在工作中愉快地构建代码好几天了 但突然我的一个项目 不是全部 失败并出现此错误消息 看看下面的答案吧 我是如何修复它的 起初我用谷歌搜索 看到很多有这个问题的人正在使用 Java 16 但我认为 错误 我正在使用 Java 11 因为
  • @EnableTransactionManagement 的范围是什么?

    我试图了解正确的放置位置 EnableTransactionManagement多个 JavaConfig 上下文的情况下的注释 考虑以下场景 我在 JPAConfig java 和 AppConfig java 中有 JPA 配置以及一组
  • Java:VM 如何在 32 位处理器上处理 64 位“long”

    JVM 如何在 32 位处理器上处理 64 位的原始 long 在多核 32 位机器上可以并行利用多个核心吗 64 位操作在 32 位机器上慢了多少 它可能使用多个核心来运行不同的线程 但不会并行使用它们进行 64 位计算 64 位长基本上
  • 尝试在没有 GatewayIntent 的情况下访问消息内容

    我希望每当我写一条打招呼的消息时 机器人都会在控制台中响应一条消息 但它只是给我一个错误 JDA MainWS ReadThread WARN JDA Attempting to access message content without
  • 具有多种值类型的 Java 枚举

    基本上我所做的是为国家编写一个枚举 我希望不仅能够像国家一样访问它们 而且还能够访问它们的缩写以及它们是否是原始殖民地 public enum States MASSACHUSETTS Massachusetts MA true MICHI
  • 在 AKKA 中,对主管调用 shutdown 是否会停止其监督的所有参与者?

    假设我有一位主管连接了 2 位演员 当我的应用程序关闭时 我想优雅地关闭这些参与者 调用supervisor shutdown 是否会停止所有参与者 还是我仍然需要手动停止我的参与者 gracias 阻止主管 https github co
  • 如何在android sdk上使用PowerMock

    我想为我的 android 项目编写一些单元测试和仪器测试 然而 我遇到了一个困扰我一段时间的问题 我需要模拟静态方法并伪造返回值来测试项目 经过一些论坛的调查 唯一的方法是使用PowerMock来模拟静态方法 这是我的 gradle 的一
  • 如何移动图像(动画)?

    我正在尝试在 x 轴上移动船 还没有键盘 我如何将运动 动画与boat png而不是任何其他图像 public class Mama extends Applet implements Runnable int width height i
  • Spock模拟inputStream导致无限循环

    我有一个代码 gridFSFile inputStream bytes 当我尝试这样测试时 given def inputStream Mock InputStream def gridFSDBFile Mock GridFSDBFile
  • Path2D 上的鼠标指针检测

    我构建了一个Path2D http docs oracle com javase 7 docs api java awt geom Path2D html表示由直线组成的未闭合形状 我希望能够检测何时单击鼠标并且鼠标指针靠近路径 在几个像素
  • Java中有类似分支/跳转表的东西吗?

    Java有类似分支表或跳转表的东西吗 分支表或跳转表是 根据维基百科 http en wikipedia org wiki Branch table 用于描述使用分支指令表将程序控制 分支 转移到程序的另一部分 或可能已动态加载的不同程序
  • Java 推断泛型类型

    我正在寻找类似的推断捕获泛型类型的概念 类似于以下方法片段 但不是捕获泛型类型的类 public

随机推荐

  • 常见报错01

    1 apt get no process found 如果你在使用apt get命令时出现 apt get no process found 错误消息 可能是以下原因之一 1 没有正在运行的apt get进程 这个错误通常会在你尝试终止一个
  • Python中的for循环和range()函数用法详解

    引言 在Python编程中 for循环和range 函数是非常常用的语法结构 用于遍历序列和重复执行一段代码块 本文将详细介绍Python中for循环和range 函数的用法 包括语法 参数 应用场景 并结合实际案例进行分析 一 for循环
  • maven 打包 releases 和 snapshots 版本

    releases 线上版本 生产环境使用的 snapshots 快照版本 开发过程中使用的 maven 打包代码到私服根据version 后面是否带有 SNAPSHOTS 来区分是打包线上版本还是快照版本 如果带有 SNAPSHOTS 打包
  • webpack + TypeScript搭建工程

    工程搭建 环境 浏览器 模块化 webpack 构建工具 更据人口文件找寻依赖关系 打包 安装 npm i webpack webpack cli D 安装插件 npm i D html webpack plugin clean webpa
  • Ubuntu18.04安装搜狗拼音输入法后无法输入中文

    系统环境 Ubuntu18 04 6 LTS 安装命令 sudo dpkg i sogoupinyin 4 2 1 145 amd64 deb 安装后显示输入法输入框 并不能输入中文 只能输入英文 解决办法 sudo apt get ins
  • 10个好用又有趣的工具类网站,赶快收藏吧

    YwTools 工具集合 www ywcoding com YwTools是一个提供许多有趣小工具的网站 这些工具能够为用户提供方便 快捷的支持 它提供许多实用性工具 比如生产力工具 免注册流程图 文本对比去重 编程类工具比如文本解码编码
  • 使用Appuploader工具将IPA上传到App Store的最新流程和步骤

    苹果官方提供的工具xcode上架ipa非常复杂麻烦 用appuploader 可以在 mac 和windows 上制作管理 证书 无需钥匙串工具 条件 1 以Windows为例 创建app打包ios需要的证书和描述文件 2 准备好一个苹果开
  • Xilinx FIFO IP核的例化和使用(含代码实例)

    使用FPGA进行数据传输处理时 数据缓存是很关键的部分 FIFO作为一种简单的缓存方案 在FPGA开发中具有广泛的应用 Xilinx为我们提供的FIFO IP核是一种先进先出 FIFO 内存队列 例化后 开发人员可自定义宽度 深度 状态标志
  • Android Menu详解

    菜单的分类 菜单是Android应用中非常重要且常见的组成部分 主要可以分为三类 选项菜单 上下文菜单 上下文操作模式以及弹出菜单 它们的主要区别如下 1 选项菜单是一个应用的主菜单项 用于放置对应用产生全局影响的操作 如搜索 设置 2 上
  • 随机采样方法整理与讲解(MCMC、Gibbs Sampling等)

    本文是对参考资料中多篇关于sampling的内容进行总结 搬运 方便以后自己翻阅 其实参考资料中的资料写的比我好 大家可以看一下 好东西多分享 PRML的第11章也是sampling 有时间后面写到PRML的笔记中去 背景 随机模拟也可以叫
  • 解决VS Code集成终端中Node命令不可用的问题

    问题 VS Code集成终端中输入node v提示 node 不是内部命令 解决方法 1 右键点击VS Code启动图标 选择属性 2 点击兼容性选项卡 3 勾选以管理员身份运行 4 打开VS Code集成终端 输入node v 成功
  • html5 js获取设备信息,js怎么获取电脑硬件信息

    想知道怎么获取电脑的硬件信息吗 下面是学习啦小编带来js怎么获取电脑硬件信息的内容 欢迎阅读 js怎么获取电脑硬件信息 1 写一个js获取userAgent属性的html文件 文件内容如下 alert window navigator us
  • Golang Map原理(底层结构、查找/新增/删除、扩缩容)

    参考 解剖Go语言map底层实现 Go语言核心手册 3 字典 一 Go Map底层结构 Go map的底层实现是一个哈希表 数组 链表 使用拉链法消除哈希冲突 因此实现map的过程实际上就是实现哈希表的过程 先来看下go map底层的具体结
  • SVN账号密码查找

    1 根据路径找到svn simple C Users Administrator AppData Roaming Subversion auth svn simple 2 执行 TSvnPwd exe 查看用户名 密码
  • Related work怎么写?

    傍晚找师兄改论文的related work 师兄一边改related work 一边教我如何写related work 小白鼠记录师兄的related work写作宝典如下 Related work精神 related work不需要写得特
  • 从键盘输入字符串,判断是否为回文字符串。 回文字符串:如果一个字符串,从前向后读和从后向前读,都是一个字符串,则称为回文串,比如adminnimda,dad,mommom。 源程序:

    package Experiment Java test14 import java util Scanner public class test04 public static void main String args Scanner
  • 嵌入式开发概述(树莓派介绍)

    目录 嵌入式定义 嵌入式芯片选型 ARM架构 ARM树莓派 嵌入式定义 国内普遍认同的嵌入式系统的定义是以应用为中心 以计算机技术为基础 软硬件可裁剪 适应应用系统对功耗 可靠性 成本 体积 功耗等严格要求的专用计算机系统 嵌入式系统是软件
  • WPF Virtualization

    WPF虚拟化技术分为UI 虚拟化和数据虚拟化 第一种方法被称为 UI 虚拟化 支持虚拟化用户界面的控件是足够聪明来创建只显示的是实际在屏幕上可见的数据项目所需的 UI 元素 例如 假设我们有一个滚动的列表框是绑定到 1 000 000 项目
  • 微信小程序上线流程

    1 打开微信公众平台扫码登录 2 点击成员管理 我是接的别人开发的版本 首先要管理员给我权限 让我成为小程序的开发者 按下图就可以添加成员了 你要是开发者直接要他给你全勾上 最后点击确认添加就行 3 点击微信开发者工具里的上传按钮或者hbu
  • C++项目实战-实际应用

    目录 典型IO的两个阶段 网络IO Linux上的五种IO模型 1 阻塞 blocking 2 非阻塞 3 IO复用 4 信号驱动 5 异步 Web Server HTTP协议 应用层的协议 简介 概述 工作原理 HTTP 请求报文格式 H