线程

Linux线上问题定位

早过忘川 提交于 2020-03-06 05:04:14
常见定位问题的方式有: 日志 系统状态 dump线程 今天用Linux命令一步一步来定位可能出现的问题程序。 1.打开linux terminal工具,敲入“top”命令如下图出现系统资源的占用情况 展示的信息太多、这里只看每个进程的cup性能信息:可能会出现3种情况。 ·第一种情况,某个线程CPU利用率一直100%,则说明是这个线程有可能有死循环。 ·第二种情况,某个线程一直在TOP 10的位置,这说明这个线程可能有性能问题(根据命令排序)。 ·第三种情况,CPU利用率高的几个线程在不停变化,说明并不是由某一个线程导致CPU 偏高。 方案 注意:如果是第一种情况,也有可能是GC造成,可以用jstat命令看一下GC情况,看看是不是因 为持久代或年老代满了,产生Full GC,导致CPU利用率持续飙高。 已经定位高cpu的PID了。 1.根据PID找到耗时高cpu的线程id,命令如下(还可把线程dump下来也可以) ps -mp pid -o THREAD,tid,time 2.拿到 tid(线程id),这里是10进制的,要转换成16进制的 printf "%x\n" 线程id 3.拿到线程id,打印线程的堆栈信息,找到出现问题的代码,命令: jstack pid | grep tid -A 30 有的在实验楼敲过,打完收工-累。 来源: CSDN 作者: TangDB。 链接:

Linux TCP server系列(4)-浅谈listen与大并发TCP连接

牧云@^-^@ 提交于 2020-03-06 04:39:37
背景: 服务器在调用 listen 和 accept 后,就会阻塞在 accept 函数上, accpet 函数返回后循环调用 accept 函数等待客户的 TCP 连接。如果这时候又大量的用户并发发起 connect 连接,那么在 listen 有队列上限 ( 最大可接受 TCP 的连接数 ) 的情况下,有多少个 connect 会成功了。试验证明,当连接数远远高于 listen 的可连接数上限时,客户端的大部分 TCP 请求会被抛弃,只有当 listen 监听队列空闲或者放弃某个连接时,才可以接收新的连接,那么我们应该如何来避免这种情况出现? 分析: (一)客户端 客户端运行初期完成所设定的一定量的 socket 创建和相应的处理线程的创建 ,然后使用 条件变量来完成线程同步 ,直到最后一个线程创建完成,才 向所有线程发出广播通知,让所有线程并发调用 connect ,连接成功则关闭连接,失败则返回,如下代码所示。 socket 创建和线程创建: int testCount=300; // 并发用户数 /* 每个进程需要自己独立的栈空间, linux 下默认栈大小是 10M ,在 32 位的机子上一个进程需要 4G 的内存空间,去掉自己的栈空间全局程序段空间,一般只有 3G 内存可以用,创建线程时就需要从这 3G 的空间中分配 10M 出来,所以最多可以分配 300 个线程

EventBus-订阅总线

橙三吉。 提交于 2020-03-06 02:57:14
EventBus-订阅总线 介绍EventBus 案例:通过EventBus给Fragment设置EditText传来的值 介绍EventBus EventBus是一种用于Android的事件发布-订阅总线,它简化了应用程序内各个组件之间进行通信的复杂度,尤其是碎片之间进行通信的问题,可以避免由于使用广播通信而带来的诸多不便。 在EventBus中有三个重点 1、发送者 用来在任意线程中,发送数据,参数是Objcet类型. 2、接收者 用来接收数据.但是接收之前需要在当前的页面注册和注销, @Override public void onStart ( ) { super . onStart ( ) ; //订阅事件 EventBus . getDefault ( ) . register ( this ) ; } @verride public void onStop ( ) { super . onStop ( ) ; //退订事件 EventBus . getDefault ( ) . unregister ( this ) ; } 3、事件 需要发送的内容,这里也可以封装成一个对象 @Subscribe ( threadMode = ThreadMode . MAIN ) public void getMsg ( EvenBus e ) { tvShow . setText

Node.js的三大特点

╄→гoц情女王★ 提交于 2020-03-06 02:17:18
单线程 Nodejs跟Nginx一样都是单线程为基础的,这里的单线程指主线程为单线程,所有的阻塞的全部放入一个线程池中,然后主线程通过队列的方式跟线程池来协作。线程池主要由一堆callback回调函数构成的,然后主线程在循环间隙中适当调用,并清空队列。 在Java、PHP或者.net等服务器端语言中,会为每一个客户端连接创建一个新的线程。而每个线程需要耗费大约2MB内存。也就是说,理论上,一个8GB内存的服务器可以同时连接的最大用户数为4000个左右。要让Web应用程序支持更多的用户,就需要增加服务器的数量,而Web应用程序的硬件成本当然就上升了。 **Node.js不为每个客户连接创建一个新的线程,而仅仅使用一个线程。**当有用户连接了,就触发一个内部事件,**通过非阻塞I/O、事件驱动机制,让Node.js程序宏观上也是并行的。**使用Node.js,一个8GB内存的服务器,可以同时处理超过4万用户的连接。 另外,单线程的带来的好处,还有操作系统完全不再有线程创建、销毁的时间开销。 坏处,就是一个用户造成了线程的崩溃,整个服务都崩溃了,其他人也崩溃了。 话不多说,上图! 上图说明,单线程也能造成宏观上的“并发”。 非堵塞I/O 当用户在访问数据库取得数据的时候,需要一段请求时间。在传统的单线程处理机制中,在执行了访问数据库代码之后,整个线程都将暂停下来,等待数据库返回结果

Reactor模式和Proactor模式

橙三吉。 提交于 2020-03-06 02:04:54
Reactor 主线程往epoll内核事件表中注册socket上的读就绪事件 主线程调用epoll_wait等待socket上有数据可读 当socket上有数据可读时,epoll_wait通知主线程,主线程则将socket可读事件放入请求队列。 睡眠在请求队列上的某个工作线程被唤醒,它从socket读取数据,并处理客户请求,然后往epoll内核事件表中注册该socket上的写就绪事件。 主线程调用epoll_wait等待socket可写 当socket可写时,epoll_wait通知主线程,主线程将socket可写事件放入请求队列 睡眠在请求队列上的某个工作线程(工作线程从请求队列读取事件后,根据事件的类型来决定如何处理它,没有必要区分读工作线程和写工作线程)被唤醒,它往socket上写入服务器处理客户请求的结果 Reactor模式的缺点:   Reactor处理耗时长的操作(如文件I/O)会造成事件分发的阻塞,影响到后续事件的处理。   因此涉及到文件I/O相关的操作,需要使用异步I/O,即使用Proactor模式效果更佳。 Proactor 主线程调用aio_read向内核注册socket上的读完成事件,并告诉内核用户缓冲区的位置,以及读操作完成时如何通知应用程序(可以用信号) 主线程继续处理其他逻辑 当socket上的读数据被读入用户缓冲区后,内核向应用进程发送一个信号

redis分布式锁的实现

爱⌒轻易说出口 提交于 2020-03-06 01:41:01
为什么要用分布式锁 使用场景 xx游戏平台举办了一个回馈用户活动,只要等级达到x等级,即可领取xx装备。可能有些人,有过这样的想,是不是,只要我速度够快,就能领到多份奖品啊,想想都美滋滋。结果,系统显示, 当前操作过于频繁,请稍后再试 。what??? 这个的话,就涉及到了锁。同个账号,当我们的第一次请求到服务器的时候,已经被加上了锁,当还没释放锁的时候,再次请求,则不能拿到锁,只能继续等待。(当然这种场景不一定要用分布式锁进行实现,比如数据库的索引唯一性也可实行,只是举个例子) 说到锁的话,则要从公司系统的架构说起了。一开始,很多公司的系统不是很庞大,为了节省资源,单机即可满足需求。对于这种单机模式的系统,我们可以用java原生的synchronized和lock这两种锁,只要锁住相应的类、对象或者方法等即可简单的时间锁机制。 但随着公司的不断发展,用户量的增加,需要对业务进行拆分。这个时候,微服务就出现了,服务拆分了,同时为了保证高可用,每个服务会根据负载等因素,选择部署不同数量的机器,进行集群管理。 在分布式系统的话,则出现了同个服务,部署在不同的机器上。因为我们上面采用的是基于JVM的锁机制,没法保证同个用户请求的锁都是同个JVM(其实可以通过设置负载均衡策略,根据用户id进行hash之类,让用户落到同一台机器上,但这种很少用,毕竟这个是属于业务的问题)

阻塞,非阻塞,同步,异步

孤街醉人 提交于 2020-03-06 00:45:02
先说说阻塞与非阻塞,这主要和程序等待消息时的状态有关 1、阻塞 程序会阻塞在某一个函数,而不往下执行,就如挂在那里一样,所有的其他业务也都不执行,为一直等到消息到来才往下执行。 2、非阻塞 程序不会阻塞在某一个函数,不等待消息到来,立即返回,往下执行。 举个例子,TCP协议中的send,系统会为其分配一块发送缓存区,假设现在总的缓存 区的大小为1000.,而缓存区里已经有了500个数据,这时调用send,发送1000个字节数据,这时如果在阻塞模式下,send的会先最多的数据放入缓存,直到缓存区满,然后程序就会阻塞在那里,一直等到将所有数据全部发出去为止,而如果在非阻塞模式下,send的会先将最多的数据放入缓存之后,就马上返回,剩余数据下回接着发送,不会卡在send函数中。 同步和异步这两个概念,其实是与消息通知机制有关的。 1、同步 发送消息,等待消息处理完后,才往下执行。就如MFC里的SendMessage(), 2、异步 发送消息,不等待消息处理完,就往下执行,让后通过特定的接口或者事件,消息通知你事情完成了。如MFC里的PostMessage() 粗略的讲了一下以上的两个概念,估计大家会问,那么阻塞与同步,非阻塞与异步有啥区别,用例说明。 比如我们现在去银行,你可以选择两种方式,取票等待和排队等待,如果你排队等待,你就得等前面所有人都办理完了,才能办理业务

多线程基础

廉价感情. 提交于 2020-03-06 00:15:12
一、线程和进程的区别: 进程是系统分配资源的最小单位,线程是系统调度的最小单位。 每个进程至少有一个线程存在,即主线程。 进程是有自己的独立地址空间的,有进程控制块(PCB)来控制进程的状态变换,也有专门的算法来控制进程的调度(先进先出,高优先比优先,短作业优先,时间片轮转等),线程是共享进程的资源的,JVM会为每一个线程划分特殊的空间: 二、并发和并行 并发: 多个进程在一个CPU下采用时间片轮转的方式,在一段时间之内,让多个进程都得以推进,称之为并发。(也就是同一时间只有一个进程在执行) 并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行 三、线程创建的方法 1.通过继承Thread类 2.实现Runnable接口 3.其他变形 四、线程常见属性 ID 是线程的唯一标识,不同线程不会重复 名称是各种调试工具用到 状态表示线程当前所处的一个情况,下面我们会进一步说明 优先级高的线程理论上来说更容易被调度到 关于后台线程,需要记住一点:JVM会在一个进程的所有非后台线程结束后,才会结束运行。 是否存活,即简单的理解,为 run 方法是否运行结束了 线程的中断问题,下面我们进一步说明 五、start()和run()方法 复写run()方法是提供给线程要做的事情的指令清单,而start()方法则是线程真正独立的去执行了 六、中断一个线程 1.调用.thread(

Java多线程与JUC——04控制线程

北慕城南 提交于 2020-03-05 21:46:41
Java的线程支持提供了一些工具方法,通过这些方法可以很好地控制线程的执行。 Join线程 Thread类中的join方法的主要作用就是同步,它可以使得线程之间的并发执行变为串行执行。具体看代码: public class ThreadTest1 { /** * join的意思是使得放弃当前线程的执行,并返回对应的线程,例如下面代码的意思就是: * 程序在 main 线程中调用t1线程的join方法,则main线程放弃cpu控制权,并返回t1线程继续执行直到线程t1执行完毕 * 所以结果是t1线程执行完后,才到主线程执行,相当于在main线程中同步t1线程,t1执行完了,main线程才有执行的机会 */ public static void main ( String [ ] args ) { //main方法是jvm进程的默认的主线程 System . out . println ( "主线程的名字:" + Thread . currentThread ( ) . getName ( ) ) ; //在main线程中创建一个新的线程,并且启动 Thread t1 = new MyThread ( "子线程1" ) ; t1 . start ( ) ; try { //调用了 t1 的 join() 方法,他会将“主线程”给挂起来,使主线程堵塞,让子线程 t1 继续执行, //当

多线程求和,记一个 synchronized 的错误使用方式

孤街醉人 提交于 2020-03-05 20:08:40
  总结:   1. 如果在单线程环境下,几个操作共享变量的方法存在数据依赖关系,那么多线程环境下它们必须是一组原子操作,且与任何修改共享变量的方法互斥。与读方法是否互斥需要看程序的设计,比如 CopyOnWrite 模式下,这些原子操作不会与读共享变量的动作互斥,可以提高读的效率,但缺点是不能保证读操作每次读到的都是最新的值。   2. 保证多线程任务的正确性,是基于各线程对共享变量访问的正确性来保证的。   3. 我们还必须保证,多线程环境下存在数据依赖或控制依赖的方法,操作结果对其它线程的可见性以及操作对其它线程来说的有序性。happen-before 原则便是基于这两点的。   4. 尤其要注意单线程情况下不存在数据依赖,但与其它线程的执行有关的动作。因为单线程下不存在数据依赖,编译器很可能会进行乱序执行。比如修改共享变量并唤醒其它线程,单线程下这两个动作是不存在数据依赖的,如何乱序执行都不会影响单线程下的执行结果。但多线程环境下,被唤醒的线程可能是需要依据共享变量的值工作的,这两个动作在多线程环境下实际是存在数据依赖的。   题目很简单,使用多线程求一亿个数的和。这篇文章主要是为了总结一下多线程编程的思路,保证多线程任务的正确性,是基于各线程对共享变量访问的安全性来保证的。   定义共享数据: public class ArraySource { //源数组