go 调试, pprof, go tool trace

go 调试, pprof, go tool trace 做 Profiling 第一步就是怎么获取应用程序的运行情况数据。go 语言提供了 runtime/pprof 和 net/http/pprof 两个库 http api // pprof 的init函数会将pprof里的一些handler注册到http.DefaultServeMux上 // 当不使用http.DefaultServeMux来提供http api时,可以查阅其init函数,自己注册handler import _ "net/http/pprof" go func() { http.ListenAndServe("0.0.0.0:8080", nil) }() http://localhost:8080/debug/pprof/ cpu go tool pprof http://localhost:8080/debug/pprof/profile?seconds=60 mem go tool pprof http://localhost:6060/debug/pprof/heap block go tool pprof http://localhost:8080/debug/pprof/block mutex go tool pprof http://localhost:6060/debug/pprof/mutex runtime/pprof // CPUProfile enables cpu profiling. Note: Default is CPU defer profile.Start(profile.CPUProfile).Stop() // GoroutineProfile enables goroutine profiling. // It returns all Goroutines alive when defer occurs. defer profile.Start(profile.GoroutineProfile).Stop() // BlockProfile enables block (contention) profiling. defer profile.Start(profile.BlockProfile).Stop() // ThreadcreationProfile enables thread creation profiling. defer profile.Start(profile.ThreadcreationProfile).Stop() // MemProfile changes which type of memory profiling to // profile the heap. defer profile.Start(profile.MemProfile).Stop() // MutexProfile enables mutex profiling. defer profile.Start(profile.MutexProfile).Stop() golang CPU profiling CPU 性能分析(CPU profiling) 是最常见的性能分析类型。 ...

2019-11-20 · 2 min · 298 words · -

VMware ESXi

VMware ESXi http://idc.wanyunshuju.com/li/580.html free license https://kb.vmware.com/s/article/2107518 虚拟机导出 各种类型的文件 .ovf OVF 模板,该模板将虚拟机或虚拟设备的状态捕获到一个自包含的包中,并且磁盘文件以压缩格式存储。 .mf .iso .vmdk 虚拟机磁盘, Virtual Machine Disk .nvram 虚拟机 BIOS 或 EFI 配置

2019-11-11 · 1 min · 24 words · -

state和status的区别

state和status的区别 state和status的区别 state: 比较常用,各种状态都可以用它,但是它更着重于一种心理状态或者物理状态。 Status: 用在人的身上一般是其身份和地位,作"状态,情形"讲时,多指政治和商业。 state倾向于condition,是一种延续性的状态。status常用于描述一个过程中的某阶段 (phase) ,类似于C语言中枚举型变量某一个固定的值,这个值属于一个已知的集合。 比如淘宝买家问卖家"我的网购现在是什么状况?" 这个问题的背景是讲话双方都清楚,交易状态有"买家选购"“买家已付款"“卖家已发货"“买家已签收"或者有"买家已 投诉"等等状态。这些状态描述一件事情发展过程中的不同阶段。而且,这些阶段的先后顺序也是双方默许的。 所以在这里可以问"What’s the status of my purchase?",此处用state不太贴切,如果硬用上去从语感上可能听着别扭。 说物态变化用state再恰当不过。如果说一个物质的四种状态,可以说"solid state”,但如果你说"solid status”,第 一,这两个词的组合不像是描述物态,更像是在说"确定的状况 (solid产生歧义’确定的/确凿的’) “;第二,这个说法即 使不被误解,也需要事先约定一组物态变化顺序,比如把这个物质从固态开始加热然后电离,可能先后经历固态、液态、气态、等离子态这四个阶段。类似先定义枚举,然后引用的方式。 扩展: ajax中readyState,statusText,onreadystatechange,window.status怎么一会state一会是status都晕乎了 state所指的状态,一般都是有限的、可列举的,status则是不可确定的。 比如 readyState - 就那么四五种值 statusText - 描述性的文字,可以任意 onreadystatechange - 那么四五种值之间发生变化 window.status - 描述性的文字,可以任意 来个形象的比方,你体重多少公斤,属于status,但说你体重属于偏瘦、正常还是偏胖,那就是state. https://www.cnblogs.com/likebeta/archive/2012/07/03/2574595.html

2019-11-08 · 1 min · 43 words · -

golang 位运算

golang 位运算 & 位运算 AND | 位运算 OR ^ 位运算 XOR &^ 位清空 (AND NOT) << 左移 >> 右移 无符号右移 https://blog.wiloon.com/?p=15522 & 操作符 假设给定数值 a,b 只有满足 a = b = 1 的情况下下 AND(a,b) = 1,否则为 0 所以AND的另外一个很好的效果是可以用于把一个整数进行清零。 func main() { var x uint8 = 0xAC // x = 10101100 x = x & 0xF0 // x = 10100000 } | 操作符, OR | 操作符对整数部分执行OR操作。回顾一下OR操作符的属性: 给定数值 a, b 当 a = 1 或者 b = 1 OR(a,b) = 1 否则为 0 我们可以对一个给定的整数选择性地使用OR操作符设置各个位的值。例如,在下面的例子中,我们使用OR运算符 (从最低位到最高位 (MSB) ) 将第3位,第7位和第8位设置为1。 ...

2019-11-06 · 1 min · 124 words · -

gnome keyring

gnome keyring install sudo pacman -S gnome-keyring libsecret vim .bashrc eval $(/usr/bin/gnome-keyring-daemon --start --components=gpg,pkcs11,secrets,ssh) export $(gnome-keyring-daemon --start --components=pkcs11,secrets,ssh,gpg) dbus-update-activation-environment --systemd DISPLAY secret-tool, 用 secret-tool 测试 gnome keyring daemon 是否正常 secret-tool 由 libsecret 提供 secret-tool store --label='Label' foo bar secret-tool lookup foo bar secret-tool store --label='Label' {attribute} {value} ... secret-tool lookup {attribute} {value} ... secret-tool clear {attribute} {value} ... secret-tool search [--all]{attribute} {value} ... secret-tool secret-tool - 通过命令行访问 GNOME keyring (以及其他任何实现了DBus Secret Service API的服务) 。 secret-tool - Store and retrieve passwords ...

2019-11-05 · 1 min · 83 words · -

TC1

TC1 https://ljr.im/articles/streamline-the-fibonacci-tc1-firmware/ docker pull python:2-slim-stretch docker run -it -name mico -v /home/wiloon/tmp/mico:/workdir python:2-slim-stretch bash apt update && apt install git wget lib32ncurses5 ln -s /usr/local/bin/python /usr/bin/python 容器bash pip install mico-cube && \ cd /workdir && \ wget http://firmware.mxchip.com/MiCoder_v1.1.Linux.tar.gz && \ tar -zxf MiCoder_v1.1.Linux.tar.gz && \ rm MiCoder_v1.1.Linux.tar.gz && \ mico config -global MICODER /workdir/MiCoder 容器bash cd /workdir && \ mico new TC1 -create-only 容器bash cd /workdir/TC1 && \ mico add https://code.aliyun.com/mico/mico-os.git/#6c465211d3ff8797cd835e400ec54a06530dd476 容器bash git clone https://github.com/cnk700i/tc1_mqtt.git && \ mv tc1_mqtt/TC1 . && \ ...

2019-11-02 · 2 min · 232 words · -

golang 百万 TCP 连接

golang 百万 TCP 连接 https://colobu.com/2019/02/23/1m-go-tcp-connection/ https://github.com/smallnest/1m-go-tcp-server

2019-11-01 · 1 min · 6 words · -

两个 iphone 同步数据

iphone 换手机, 两个 iphone 同步数据, new iphone, sync 旧手机关掉 vpn 旧手机备份和删除照片 旧手机删除 trust 新 iphone 开机 选完语言之后停在 quick start 页面 把旧手机靠近新手机 在新手机上点 continue 用旧手机扫新手机屏幕 按提示操作 选择直接复制不选从icloud同步 check list duo mobile, 新手机 app 激活之后, 旧手机的 app 就不能用了 webex 重新登录 bitwarden, 新手机上重新输入密码 ultra mobile eSIM, wifi calling hsbc, 先在旧手机里操作删除保安密码器, 再去新手机登录, 拍护照的照片可能会失败, 失败三次之后会引导输入密码登录 银行 app 重新登录, 开 faceid 微信, 支付宝 开 faceid 支付

2019-11-01 · 1 min · 60 words · -

堆组织表、索引组织表、索引聚簇表

堆组织表、索引组织表、索引聚簇表 版权声明: 本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 https://blog.csdn.net/pianzif/article/details/32106971 堆组织表就不说了,其索引中记录了记录所在位置的rowid,查找的时候先找索引,然后再根据索引rowid找到块中的行数据 索引组织表,其行数据以索引形式存放,因此找到索引,就等于找到了行数据。 堆组织表的数据是散放的,索引和表的数据是分离的 索引组织表的索引和数据是在一起的 堆组织表的存储速度因为不用考虑排序, 所以存储速度会比较快. 但是要查找符合某个条件的记录, 就必须得读取全部的记录以便筛选. 而这个时候为了加快查询速度, 索引就出现了, 索引是针对少量特定字段的值拿出来进行排序存储, 并记录在表中的位置, 而因为索引是有序的, 所以就会很容易通过索引查询到具体的记录位置, 然后再根据记录位置直接从表中读取该记录. 同时因为索引的字段较少, 所以索引通常会比其基表小得多. 从上面通过索引访问表记录的方式可以看出, 当要访问的数据量较大时, 通过每一条记录的位置去访问原始记录, 每一条符合条件的记录都需要经过索引访问后再访问基表这样一个复杂的过程, 这会花费很多时间, 同样, 如果不经过索引而直接查询表, 也可能因为表字段太多, 记录较大的情况下把全部的数据读取进来, 这也会花费很多时间. 那怎么办呢? 这个时候就会想到, 如果表中数据本身就是有序的, 这样查询表的时候就可以快速的找到符合条件的记录位置, 而很容易判断符合条件记录的位置, 这样只需要读取一小部分数据出来就可以了, 不需要全表记录都读取出来进行判断. 索引表就这样产生了.当然索引表中插入,更新资料的时候可能会因为需要排序而将数据重组, 这时候数据插入或更新速度会比堆组织表慢一些. 如果堆组织表上有索引, 那么对堆组织表的插入也会因为要修改索引而变慢 我们可以看到堆组织表+索引的方式 与 索引表 都能够实现数据的快速查找, 那为什么不全部采用索引表呢, 这样不是很简单吗? 我能想到的是前者我们可以针对不同的查找条件建立多个索引, 而后者却不行, 后者只能对某一组查询条件有效 堆组织表 (heap organized table) Oracle中有很多类型的表,像堆组织表、索引组织表、索引聚簇表等等。首先,我将从最基本、最常用的堆组织表 (heap organized table) 介绍。 通常我们默认建的表就是堆组织表。语法 (详细语法请参见Oracle官方文档) 如下: Create table test( ...

2019-10-29 · 9 min · 1767 words · -

MySQL 默认排序

MySQL 默认排序 不加order by 的情况 下, 顺序 不能保证, 不同存储引擎, 有过增删改操作 都有可能 影响默认顺序, 默认排序只依赖于内部实现, 不同版本的MySQL也有可能 不同. 所以不能依赖默认排序. https://my.oschina.net/alarm1673/blog/1814508 https://stackoverflow.com/questions/8746519/sql-what-is-the-default-order-by-of-queries

2019-10-29 · 1 min · 18 words · -

jdbi

jdbi JDBI jdbi jdbi是我比较喜欢的一个数据库中间件,它是非 ORM 的,特别适合于数据库固定不变的场景,即不会对应多种数据库,以后也不会更换数据库的场景。 如果不是这种场景,那么使用jdbc或者最好选择hibernate等对多种数据库兼容较好的中间件。 基于上述使用场景,jdbi的优点有: 和 jdbci 比较接近,使用和掌握非常简单。 与时俱进,例如说现在最新的 jdbi3,增加了流式编程函数式等编程风格。 源代码的实现思路非常清晰,有一种美感。使用jdbi封装出的数据库代码也非常清晰。 jdbi 的两种风格 Fluent Api handle.createUpdate(“INSERT INTO user(id, name) VALUES (:id, :name)”) .bind(“id”, 2) .bind(“name”, “Clarice”) .execute(); 这里就是java8的流式风格,用连贯式表达式将一个sql实现串在一起 Declarative Api // Define your own declarative interface public interface UserDao { @SqlUpdate("CREATE TABLE user (id INTEGER PRIMARY KEY, name VARCHAR)") void createTable(); @SqlUpdate("INSERT INTO user(id, name) VALUES (?, ?)") void insertPositional(int id, String name); @SqlUpdate("INSERT INTO user(id, name) VALUES (:id, :name)") void insertNamed(@Bind("id") int id, @Bind("name") String name); @SqlUpdate("INSERT INTO user(id, name) VALUES (:id, :name)") void insertBean(@BindBean User user); @SqlQuery("SELECT * FROM user ORDER BY name") @RegisterBeanMapper(User.class) List<User> listUsers(); } 声明式的主要是使用注解来实现,在实际的面向对象风格的代码中,我个人觉得声明式的比较简洁,容易阅读和维护。所以下面都按照Declarative Api的方式。 ...

2019-10-29 · 1 min · 105 words · -

linux typeset

linux typeset https://blog.csdn.net/blackmanren/article/details/9281201 typeset 用于设置变量属性, 如大小写,宽度,左右对齐等都可以用typeset来控制, 当用typeset改变一个变量的属性时,这种改变是永久的,下面以ksh为例,演示typeset的几种典型用法 typeset的-u选项可以将一个变量的字符变成大写 /home/lee#typeset -u var=abc /home/lee#echo $var ABC 3:typeset的-l选项将一个变量的字符变成小写 /home/lee#typeset -l var=ABC /home/lee#echo $var abc typeset的-L选项把变量变成一个左对齐的4个字符串,有些像字符串截取 /home/lee#typeset -L4 var=abcdefg /home/lee#echo $var abcd typeset的-R选项把变量变成一个右对齐的4个字符串 /home/lee#typeset -R4 var=abcdefg /home/lee#echo $var defg typeset的-Z选项把串变成一个空填充,占15个字符位的串,冒号用来保护空白符 typeset -Z15 var=“abc ddd” /home/lee#echo “$var” ^^^^^^^^abc ddd #^为空白 /home/lee#typeset -LZ15 var=“abc 123” /home/lee#echo “$var$var” abc 123 abc 123 7:变量n是一个被设置成一个整数的变量,typeset命令将整数n前面补齐0,共15个字符位 /home/lee#typeset -i n=24 /home/lee#typeset -Z15 n /home/lee#echo $n 000000000000024 8:变量answer被给定一个值-Yes并变成一个小写,左对齐,一个字符的串 /home/lee#typeset -lL1 answer=Yes /home/lee#echo $answer ...

2019-10-28 · 1 min · 113 words · -

ConcurrentLinkedDeque

ConcurrentLinkedDeque 非阻塞线程安全列表——ConcurrentLinkedDeque应用举例 在java中,最常用的数据结构可能是列表。有数目不详的元素列表,你可以添加、阅读、或删除任何位置的元素。此外,并发列表允许不同的线程列表中添加或删除元素时不产生任何数据不一致。非阻塞列表提供如下操作,如果操作不能立即完成,列出抛出异常或者返回一个null值。Java 7中引入了ConcurrentLinkedDeque类,它实现了一个非阻塞并发列表,在本教程中,我们将学习使用这个类。 在这个例子中,我们将实现一个示例使用以下两个不同的任务: 一个将大量数据添加到一个列表中 一个大量地从同样的列表中删除数据 让我们为每个任务创建的线程: package com.howtodoinjava.demo.multithreading.concurrentLinkedDequeExample; import java.util.concurrent.ConcurrentLinkedDeque; public class AddTask implements Runnable { private ConcurrentLinkedDeque<String> list; public AddTask(ConcurrentLinkedDeque<String> list) { this.list = list; } @Override public void run() { String name = Thread.currentThread().getName(); for (int i = 0; i < 10000; i++) { list.add(name + ": Element " + i); } } } 和: packagecom.howtodoinjava.demo.multithreading.concurrentLinkedDequeExample; importjava.util.concurrent.ConcurrentLinkedDeque; publicclass RemoveTask implementsRunnable { privateConcurrentLinkedDeque<String> list; publicRemoveTask(ConcurrentLinkedDeque<String> list) { this.list = list; } @Override publicvoid run() { for(inti = 0; i < 5000; i++) { list.pollFirst(); list.pollLast(); } } } ...

2019-10-23 · 2 min · 288 words · -

ansible 变量

ansible 变量 ram_size: “{{ (ansible_memtotal_mb * 0.8)|int }}” --- - hosts: 'all' vars: var0: 'value0'

2019-10-21 · 1 min · 15 words · -

application start script

application start script #! /usr/bin/env bash APP_HOME=/data/server/app0 APP_NAME=app0 PID_FILE=/var/run/app0.pid startApp(){ cd ${APP_HOME} nohup java -jar ${APP_NAME}.jar > log 2>&1 & echo $! > ${PID_FILE}; } stopApp(){ kill `cat ${PID_FILE}` } case $1 in start) startApp ;; stop) stopApp ;; restart) stopApp startApp ;; *) echo "usage: wrapper {start|stop|restart}" ;; esac exit 0

2019-10-21 · 1 min · 52 words · -

Java Mission Control, jmc

Java Mission Control, jmc https://github.com/JDKMissionControl/jmc https://www.oracle.com/java/technologies/javase-overview.html download https://ci.adoptopenjdk.net/view/JMC/job/jmc-latest/

2019-10-14 · 1 min · 8 words · -

redis thread

redis thread https://www.cnblogs.com/traditional/p/13273089.html 在 Redis4.0 之前,Redis 是单线程运行的 但是单线程并不代表效率就低 因为底层采用了基于 epoll 的 IO 多路复用

2019-10-11 · 1 min · 13 words · -

架构, 架构师, architecture

架构, 架构师, architecture 架构师: architect 架构: architecture 软件架构 软件架构 (software architecture) 就是软件的基本结构。 分层架构 分层架构 (layered architecture) 是最常见的软件架构,也是事实上的标准架构。如果你不知道要用什么架构,那就用它。 这种架构将软件分成若干个水平层,每一层都有清晰的角色和分工,不需要知道其他层的细节。层与层之间通过接口通信。 虽然没有明确约定,软件一定要分成多少层,但是四层的结构最常见。 表现层 (presentation) : 用户界面,负责视觉和用户互动 业务层 (business) : 实现业务逻辑 持久层 (persistence) : 提供数据,SQL 语句就放在这一层 数据库 (database) : 保存数据 有的软件在逻辑层和持久层之间,加了一个服务层 (service) ,提供不同业务逻辑需要的一些通用接口。 用户的请求将依次通过这四层的处理,不能跳过其中任何一层。 事件驱动架构 事件 (event) 是状态发生变化时,软件发出的通知。 事件驱动架构 (event-driven architecture) 就是通过事件进行通信的软件架构。它分成四个部分。 事件队列 (event queue) : 接收事件的入口 分发器 (event mediator) : 将不同的事件分发到不同的业务逻辑单元 事件通道 (event channel) : 分发器与处理器之间的联系渠道 事件处理器 (event processor) : 实现业务逻辑,处理完成后会发出事件,触发下一步操作 微核架构 微核架构 (microkernel architecture) 又称为"插件架构" (plug-in architecture) ,指的是软件的内核相对较小,主要功能和业务逻辑都通过插件实现。 ...

2019-10-11 · 2 min · 326 words · -

获取网络时间

获取网络时间 public class GetNetworkTime { public static void main(String[] args) { String webUrl2 = "http://www.baidu.com";//百度 String webUrl3 = "http://www.taobao.com";//淘宝 String webUrl4 = "http://www.ntsc.ac.cn";//中国科学院国家授时中心 String webUrl5 = "http://www.360.cn";//360 System.out.println(getWebsiteDatetime(webUrl2) + " [百度]"); System.out.println(getWebsiteDatetime(webUrl3) + " [淘宝]"); System.out.println(getWebsiteDatetime(webUrl4) + " [中国科学院国家授时中心]"); System.out.println(getWebsiteDatetime(webUrl5) + " [360安全卫士]"); } /** * 获取指定网站的日期时间 * * @param webUrl * @return * @author SHANHY * @date 2015年11月27日 */ private static String getWebsiteDatetime(String webUrl){ try { URL url = new URL(webUrl);// 取得资源对象 URLConnection uc = url.openConnection();// 生成连接对象 uc.connect();// 发出连接 long ld = uc.getDate();// 读取网站日期时间 Date date = new Date(ld);// 转换为标准时间对象 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);// 输出北京时间 return sdf.format(date); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } } https://blog.csdn.net/catoop/article/details/50076879

2019-10-09 · 1 min · 119 words · -

netty Reactor 模式

netty Reactor模式 Reactor模式的角色构成(Reactor模式一共有5中角色构成): Handle (句柄或描述符,在Windows下称为句柄,在Linux下称为描述符):本质上表示一种资源(比如说文件描述符,或是针对网络编程中的socket描述符),是由操作系统提供的;该资源用于表示一个个的事件,事件既可以来自于外部,也可以来自于内部;外部事件比如说客户端的连接请求,客户端发送过来的数据等;内部事件比如说操作系统产生的定时事件等。它本质上就是一个文件描述符,Handle是事件产生的发源地。 Synchronous Event Demultiplexer (同步事件分离器):它本身是一个系统调用,用于等待事件的发生(事件可能是一个,也可能是多个)。调用方在调用它的时候会被阻塞,一直阻塞到同步事件分离器上有事件产生为止。对于Linux来说,同步事件分离器指的就是常用的I/O多路复用机制,比如说select、poll、epoll等。在Java NIO领域中,同步事件分离器对应的组件就是Selector;对应的阻塞方法就是select方法。 Event Handler (事件处理器):本身由多个回调方法构成,这些回调方法构成了与应用相关的对于某个事件的反馈机制。在Java NIO领域中并没有提供事件处理器机制让我们调用或去进行回调,是由我们自己编写代码完成的。Netty相比于Java NIO来说,在事件处理器这个角色上进行了一个升级,它为我们开发者提供了大量的回调方法,供我们在特定事件产生时实现相应的回调方法进行业务逻辑的处理,即,ChannelHandler。ChannelHandler中的方法对应的都是一个个事件的回调。 Concrete Event Handler (具体事件处理器):是事件处理器的实现。它本身实现了事件处理器所提供的各种回调方法,从而实现了特定于业务的逻辑。它本质上就是我们所编写的一个个的处理器实现。 Initiation Dispatcher (初始分发器):实际上就是Reactor角色。它本身定义了一些规范,这些规范用于控制事件的调度方式,同时又提供了应用进行事件处理器的注册、删除等设施。它本身是整个事件处理器的核心所在,Initiation Dispatcher会通过 Synchronous Event Demultiplexer 来等待事件的发生。一旦事件发生,Initiation Dispatcher 首先会分离出每一个事件,然后调用事件处理器,最后调用相关的回调方法来处理这些事件。Netty中ChannelHandler 里的一个个回调方法都是由 bossGroup 或 workGroup 中的某个EventLoop来调用的。 Reactor模式流程 ① 初始化Initiation Dispatcher,然后将若干个Concrete Event Handler注册到Initiation Dispatcher中。当应用向Initiation Dispatcher注册Concrete Event Handler时,会在注册的同时指定感兴趣的事件,即,应用会标识出该事件处理器希望Initiation Dispatcher在某些事件发生时向其发出通知,事件通过Handle来标识,而Concrete Event Handler又持有该Handle。这样,事件 ————> Handle ————> Concrete Event Handler 就关联起来了。 ② Initiation Dispatcher 会要求每个事件处理器向其传递内部的Handle。该Handle向操作系统标识了事件处理器。 ③ 当所有的Concrete Event Handler都注册完毕后,应用会调用handle_events方法来启动Initiation Dispatcher的事件循环。这是,Initiation Dispatcher会将每个注册的Concrete Event Handler的Handle合并起来,并使用Synchronous Event Demultiplexer(同步事件分离器)同步阻塞的等待事件的发生。比如说,TCP协议层会使用select同步事件分离器操作来等待客户端发送的数据到达连接的socket handler上。 比如,在Java中通过Selector的select()方法来实现这个同步阻塞等待事件发生的操作。在Linux操作系统下,select()的实现中 a)会将已经注册到Initiation Dispatcher的事件调用epollCtl(epfd, opcode, fd, events)注册到linux系统中,这里fd表示Handle,events表示我们所感兴趣的Handle的事件;b)通过调用epollWait方法同步阻塞的等待已经注册的事件的发生。不同事件源上的事件可能同时发生,一旦有事件被触发了,epollWait方法就会返回;c)最后通过发生的事件找到相关联的SelectorKeyImpl对象,并设置其发生的事件为就绪状态,然后将SelectorKeyImpl放入selectedSet中。这样一来我们就可以通过Selector.selectedKeys()方法得到事件就绪的SelectorKeyImpl集合了。 ④ 当与某个事件源对应的Handle变为ready状态时(比如说,TCP socket变为等待读状态时),Synchronous Event Demultiplexer就会通知Initiation Dispatcher。 ⑤ Initiation Dispatcher会触发事件处理器的回调方法,从而响应这个处于ready状态的Handle。当事件发生时,Initiation Dispatcher会将被事件源激活的Handle作为『key』来寻找并分发恰当的事件处理器回调方法。 ⑥ Initiation Dispatcher会回调事件处理器的handle_event(type)回调方法来执行特定于应用的功能(开发者自己所编写的功能),从而相应这个事件。所发生的事件类型可以作为该方法参数并被该方法内部使用来执行额外的特定于服务的分离与分发。 ...

2019-10-03 · 1 min · 186 words · -