线程

白话理解goroutine

点点圈 提交于 2020-02-29 07:53:17
要理解这个事儿首先得了解操作系统是怎么玩线程的。一个线程就是一个栈加一堆资源。操作系统一会让cpu跑线程A,一会让cpu跑线程B,靠A和B的栈来保存A和B的执行状态。每个线程都有他自己的栈。 但是线程又老贵了,花不起那个钱,所以go发明了goroutine。大致就是说给每个goroutine弄一个分配在heap里面的栈来模拟线程栈。比方说有3个goroutine,A,B,C,就在heap上弄三个栈出来。然后Go让一个单线程的scheduler开始跑他们仨。相当于 { A(); B(); C() },连续的,串行的跑。 和操作系统不太一样的是,操作系统可以随时随地把你线程停掉,切换到另一个线程。这个单线程的scheduler没那个能力啊,他就是user space的一段朴素的代码,他跑着A的时候控制权是在A的代码里面的。A自己不退出谁也没办法。 所以A跑一小段后需要主动说,老大(scheduler),我不想跑了,帮我把我的所有的状态保存在我自己的栈上面,让我歇一会吧。这时候你可以看做A返回了。A返回了B就可以跑了,然后B跑一小段说,跑够了,保存状态,返回,然后C再跑。C跑一段也返回了。 这样跑完{A(); B(); C()}之后,我们发现,好像他们都只跑了一小段啊。所以外面要包一个循环,大致是: goroutine_list = [A, B, C] while(goroutine):

线程和进程的区别是什么?

谁说我不能喝 提交于 2020-02-29 07:48:11
首先来一句概括的总论: 进程和线程都是一个时间段的描述,是CPU工作时间段的描述。 下面细说背景 : CPU+RAM+各种资源(比如显卡,光驱,键盘,GPS, 等等外设)构成我们的电脑,但是电脑的运行,实际就是CPU和相关寄存器以及RAM之间的事情。 一个最最基础的事实 :CPU太快,太快,太快了,寄存器仅仅能够追的上他的脚步,RAM和别的挂在各总线上的设备完全是望其项背。那当多个任务要执行的时候怎么办呢?轮流着来?或者谁优先级高谁来?不管怎么样的策略,一句话就是在CPU看来就是轮流着来。 一个必须知道的事实 :执行一段程序代码,实现一个功能的过程介绍 ,当得到CPU的时候,相关的资源必须也已经就位,就是显卡啊,GPS啊什么的必须就位,然后CPU开始执行。这里除了CPU以外所有的就构成了这个程序的执行环境,也就是我们所定义的程序上下文。当这个程序执行完了,或者分配给他的CPU执行时间用完了,那它就要被切换出去,等待下一次CPU的临幸。在被切换出去的最后一步工作就是保存程序上下文,因为这个是下次他被CPU临幸的运行环境,必须保存。 串联起来的事实 :前面讲过在CPU看来所有的任务都是一个一个的轮流执行的,具体的轮流方法就是: 先加载程序A的上下文,然后开始执行A,保存程序A的上下文,调入下一个要执行的程序B的程序上下文,然后开始执行B,保存程序B的上下文 。。。 。 ========

Jprofile解析dump文件使用详解

ⅰ亾dé卋堺 提交于 2020-02-29 06:36:02
1 Jprofile简介 官网 下载对应的系统版本即可 性能查看工具JProfiler,可用于查看java执行效率,查看线程状态,查看内存占用与内存对象,还可以分析dump日志. 2 功能简介 选择attach to a locally running jvm 选择需要查看运行的jvm,双击或者点击start 等待进度完成,弹出模式选择 Instrumentation模式记录所有的信息。包括方法执行次数等Sampling模式则只支持部分功能,不纪录方法调用次数等,并且更为安全 由于纪录信息很多,java运行会变的比正常执行慢很多,sampling模式则不会 常规使用选择sampling模式即可,当需要调查方法执行次数才需要选择Instrumentation模式,模式切换需要重启jprofiler 点击OK 选择Live Momory可以查看内存中的对象和大小 选择cpu views点击下图框中的按钮来纪录cpu的执行时间 这时候可以在外部对需要录的jvm操作进行记录了,得出的结果可以轻松看出方法执行调用过程与消耗时间比例: 根据cpu截图的信息,可以找到效率低的地方进行处理,如果是Instrumentation模式则在时间位置会显示调用次数 在Thread界面则可以实时查看线程运行状态,黄色的是wait 红色是block 绿色的是runnable蓝色是网络和I/O请求状态

tigase网络核心SockThread详解

倾然丶 夕夏残阳落幕 提交于 2020-02-29 06:24:58
总述 SocketThread类是一个很底层的类,在初始化时调用了Selector.open(clientsSel)。 socketReadThread nThread个 socketWriteThread nThread个 ResultsListener nThread个 completionService一个,池化线程nThread个,在sockThread.run里被submit,ResultsListener里进行completionService.take().get()取出执行结果。 forCompletion有序队列一个,在socketThread.run里开始add,同一方法立即被从最小依次取出,然后submit给completionService。 waiting有序队列一个,recreateSelector阶段存在add,最大来源是addSocketService静态方法,在 socketThread.run最后阶段的addAllWaiting时注册Channel时把waiting里的IOService取出做为附加对象 绑定。 重点方法 主方法+两个有序队列,一个是等待处理队列,一个是完成队列。 forCompletion完成队列里的内容,交由具体的completionService完成后,由ResultListener相关线程处理最终结果。 主方法

远程调试方式

烂漫一生 提交于 2020-02-29 05:53:37
使用特定JVM参数运行服务端代码 要让远程服务器运行的代码支持远程调试,则启动的时候必须加上特定的JVM参数,这些参数是: 1 -Xdebug -Xrunjdwp:transport=dt_socket,suspend=n,server=y,address=${debug_port} 其中的${debug_port}是用户自定义的,为debug端口,本例以5555端口为例。 transport: 表示信息传递的连接方式, 其中,dt_socket是指用SOCKET模式,另有dt_shmem指用共享内存方式,其中,dt_shmem只适用于Windows平台。 server: server=y 表示是监听其他debug client端的请求 address 表示等待调试的连接网络端口 suspend 表示是否在启动目标虚拟机后挂起虚拟机,如果要调试启动过程,请使用y 参数说明: address为远程调试的端口号,目前我们服务器上8412是一个开放的端口(staging环境已验证) -Xrunjdwp 使用jdwp( Java Debug Wire Protocol)进行调试 transport=dt_socket 使用socket方式进行连接,还可以使用其他通信方式如(dt_shmem 共享内存) suspend=n JVM监听address端口传来的信号时不挂起JVM中运行的进程

(转)编程思想之多线程与多进程(1)——以操作系统的角度述说线程与进程

十年热恋 提交于 2020-02-29 05:33:23
1、什么是线程 什么是线程?线程与进程与有什么关系?这是一个非常抽象的问题,也是一个特别广的话题,涉及到非常多的知识。我不能确保能把它讲的话,也不能确保讲的内容全部都正确。即使这样,我也希望尽可能地把他讲通俗一点,讲的明白一点,因为这是个一直困扰我很久的,扑朔迷离的知识领域,希望通过我的理解揭开它一层一层神秘的面纱。 2、任务调度 线程是什么?要理解这个概念,须要先了解一下操作系统的一些相关概念。大部分操作系统(如Windows、Linux)的任务调度是采用时间片轮转的抢占式调度方式,也就是说一个任务执行一小段时间后强制暂停去执行下一个任务,每个任务轮流执行。任务执行的一小段时间叫做时间片,任务正在执行时的状态叫运行状态,任务执行一段时间后强制暂停去执行下一个任务,被暂停的任务就处于就绪状态等待下一个属于它的时间片的到来。这样每个任务都能得到执行,由于CPU的执行效率非常高,时间片非常短,在各个任务之间快速地切换,给人的感觉就是多个任务在“同时进行”,这也就是我们所说的并发(别觉得并发有多高深,它的实现很复杂,但它的概念很简单,就是一句话:多个任务同时执行)。多任务运行过程的示意图如下: 图 1:操作系统中的任务调度 3、进程 我们都知道计算机的核心是CPU,它承担了所有的计算任务;而操作系统是计算机的管理者,它负责任务的调度、资源的分配和管理,统领整个计算机硬件

基于任务的异步编程

我是研究僧i 提交于 2020-02-29 04:41:08
博客迁移 记录《Effective C#》学习过程。 任务运行的几种方法 //1.new方式实例化一个Task,需要通过Start方法启动 Task task = new Task(() => { Console.WriteLine($"task1的线程ID为{Thread.CurrentThread.ManagedThreadId}"); }); task.Start(); //2.Task.Factory.StartNew(Action action)创建和启动一个Task Task task2 = Task.Factory.StartNew(() => { Console.WriteLine($"task2的线程ID为{Thread.CurrentThread.ManagedThreadId}"); }); //3.Task.Run(Action action)将任务放在线程池队列,返回并启动一个Task Task task3 = Task.Run(() => { Console.WriteLine($"task3的线程ID为{ Thread.CurrentThread.ManagedThreadId}"); }); View Code 使用异步方法执行异步工作 对于调用异步方法的主调方法来说,只要异步方法已经返回,这里返回的是Task对象,它就可以继续往下执行。

6月10号

南楼画角 提交于 2020-02-29 03:47:27
阻塞io(blocking IO) 当我们用套接字通讯时套接字对象调用revform方法 系统内核就开始了network io 的第一个阶段 wair for data 这是系统内核就等待足够的数据到来 而用户整个进程就会被阻塞 当系统内核等到了数据 它就会将数据从缓存中拷贝到 用户进程的内存中 然后系统返回结果给recv 用户进程接受到数据 解除阻塞状态 进入就绪态 重新运行起来 所以在 wait for data 和copy data 用户进程都属于阻塞的状态 简单的解决办法就是让服务器端使用多线程或者多进程,目的是为了让每一个接口都有用一个独立的线程或进程 这样任何一个连接有网络io都 不会影响其他线程或进程的运行 它阻塞它的 我运行我的 但是 开启多线程或多进程 在遇到同时要想相应巨大连接请求的时候 都会严重占据系统资源 降低服务器对外界的响应速度 所以开启多进程或 多线程并不能完全解决网络阻塞io这个问题 当然 我们会想到你无线开线程和进程系统会扛不住 我们可以限制线程和进程的同步开启 可以用线程池或进程池 来维持一定合理数量的线程或 进程 并让空闲的线程重新承担新的执行任务 规定只能同时开线程池里面规定数量的线程 减少创建和关闭连接的频率 降低系统的开销 但是这样也并非完美 线程池和进程池 能一定程度上缓解 系统的开销 但是如果用户数量大大超出 线程池始终有自己的上线

小程序运行逻辑说明

时光怂恿深爱的人放手 提交于 2020-02-29 02:05:09
小程序环境说明 小程序运行环境分为 逻辑层、渲染层 ;同样这两个层面分别由两个线程进行管理; 逻辑层: js脚本;jsCore线程管理 渲染层: wxml、wxss运行层;webview线程管理; 一个小程序存在多个界面,所以渲染层存在多个WebView线程,这两个线程的通信会经由微信客户端做中转,逻辑层发送网络请求也经由客户端转发。 小程序运行流程 打开小程序之前会把小程序的代码包下载到本地; 通过app.json的pages页面配置获取所有的页面路径; 读取pages中的第一个配置的页面进行装载运行,渲染页面; 小程序启动之后,在 app.js 定义的 App 实例的 onLaunch 回调会被执行(该APP实例是小程序唯一的,是全部页面共享的,更多说明:https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/app.html ); 页面开始装载时会先会先根据 json 配置生成一个界面,顶部的颜色和文字你都可以在这个 json 文件里边定义好 紧接着客户端就会装载这个页面的 WXML 结构和 WXSS 样式; 最后客户端会装载 js文件; 在js文件内部会存在一个构造器,该构造器内部会有data数据以及function方法等,框架会把data 数据和 index.wxml

三个线程交替顺序打印ABC

早过忘川 提交于 2020-02-29 01:38:46
题目描述 建立三个线程A、B、C,A线程打印10次字母A,B线程打印10次字母B,C线程打印10次字母C,但是要求三个线程同时运行,并且实现交替打印,即按照ABCABCABC的顺序打印。 解决办法 :使用synchronized, wait和notifyAll 思路 :使用同步块和wait、notify的方法控制三个线程的执行次序。具体方法如下:从大的方向上来讲,该问题为三线程间的同步唤醒操作,主要的目的就是ThreadA->ThreadB->ThreadC->ThreadA循环执行三个线程。为了控制线程执行的顺序,那么就必须要确定唤醒、等待的顺序,所以每一个线程必须同时持有两个对象锁,才能进行打印操作。一个对象锁是prev,就是前一个线程所对应的对象锁,其主要作用是保证当前线程一定是在前一个线程操作完成后(即前一个线程释放了其对应的对象锁)才开始执行。还有一个锁就是自身对象锁。主要的思想就是,为了控制执行的顺序,必须要先持有prev锁(也就前一个线程要释放其自身对象锁),然后当前线程再申请自己对象锁,两者兼备时打印。之后首先调用self.notify()唤醒下一个等待线程(注意notify不会立即释放对象锁,只有等到同步块代码执行完毕后才会释放),再调用prev.wait()立即释放prev对象锁,当前线程进入休眠,等待其他线程的notify操作再次唤醒。 原文链接https:/