线程

ThreadFactory & ThreadGroup

本秂侑毒 提交于 2020-03-01 23:56:21
原本想给 多线程任务 做一个挂起(暂停)功能,然后配合 httpcomponents-asyncclient 并发测试,结果意外令人汗颜,竟然CPU占用100%。。。 使用VisualVM观察CPU抽样,发现 org.apache.http.impl.nio.reactor.AbstractIOReactor.execute() 方法总是占用大部分CPU,然而没调用挂起操作时却一切正常。 这挂起操作的其中一环需要中断线程,这些线程均出产自自定义ThreadFactory : public class GroupThreadFactory implements ThreadFactory { private final ThreadGroup group; private final AtomicInteger threadNumber; public GroupThreadFactory() { this.group = new ThreadGroup("WorkerGroup"); this.threadNumber = new AtomicInteger(1); } public Thread newThread(Runnable r) { Thread t = new Thread(null, r, "pool-thread-" + threadNumber

并发编程的理论基石

南楼画角 提交于 2020-03-01 23:44:36
一、进程和线程 1.操作系统、进程、线程的关系 操作系统是包含多个进程的容器,而每个进程又是容纳多个线程的容器。 2.Oracle 官方定义 官方定义 进程:使用 fork(2) 系统调用创建的UNIX 环境(例如文件描述符,用户 ID 等),它被设置为运行程序。 线程:在进程上下文执行的一系列指令。 3.什么是进程 进程(Process)是程序的运行实例。 进程是程序向操作系统申请资源(如内存空间和文件句柄)的基本单位。 在用户下达运行程序的命令后,就会产生进程,任务管理器中的每一个应用都是一个进程。谷歌浏览器的每个标签页和插件都是一个进程。 4.什么是线程 线程是操作系统能够进行资源调度的最小单位,它被包含在进程之中,是进程中的实际运作单位,每个线程执行的都是进程代码的某个片段,特定的线程总是在执行特定的任务。 5.进程和线程的关系 5.1 起源不同 先有进程,后有线程。进程由于资源利用率、公平性和便利性诞生。处理器的速度往往比外设的速度快(键盘、鼠标等),为了提高 CPU 的利用率,诞生了线程,目的就是为了提高程序的执行效率。 5.2 概念不同 进程是资源分配的最小单位。 线程是程序执行的最小单位(线程是操作系统能够进行资源调度的最小单位,同个进程中的线程也可以被同时调度到多个 CPU 上运行),线程也被称为轻量级进程。 5.3 内存共享方式不同 默认情况下

JVM详解

◇◆丶佛笑我妖孽 提交于 2020-03-01 23:39:44
JVM详解 JVM详解 1、JVM 运行时数据区 2、方法区 3、堆内存: 4、虚拟机栈: 5、java程序运行过程(例子): 6、JVM 知识图谱: 1、JVM 运行时数据区 线程共享:所有线程能访问这块内存数据,随虚拟机或者GC而创建和销毁 线程独占:每个线程都会有它独立的空间,随线程生命周期而创建和销毁 2、方法区 作用:存储加载的类信息、常量、静态变量、JIT编译后的代码等数据。 GC:方法区存在垃圾回收,但是回收效率低 回收主要针对常量池的回收,和类型的卸载; 当方法区无法满足内存需求时,报OOM. 3、堆内存: 作用:唯一的目的就是存放对象实例,几乎所有的对象、数组都在这里存放。 对于大多数应用来说,堆是JVM管理的内存中最大的一块内存区域,也是最容易OOM的区域。 大多数JVM都将堆实现为大小可扩展的(通过-Xmx、-Xms控制)。 对象何时被回收:引用计数器算法(存在两个对象相互引用的问题) 可达性分析算法:主流的商用程序语言(java)都是通过可达性分析算法来判定对象是否存活, GC Roots可以是:虚拟机栈、方法中静态属性引用的对象、方法区中常量引用的对象,Native方法引用对象、 4、虚拟机栈: 线程中方法执行的模型,每个方法执行时,就会在虚拟机中创建一个栈帧,每个方法从调用到执行的过程,就对应着栈帧在虚拟机栈中从入栈到出栈的过程。 本地方法栈

死锁原因

杀马特。学长 韩版系。学妹 提交于 2020-03-01 23:12:32
1.交叉锁会导致程序死锁 这个大家都很熟悉了,就是线程A持有R1的锁又想获取R2的锁,线程B持有R2的锁又想获取R1的锁。两个谁也不放弃自己的又想要对方的,就导致死锁了。 一般交叉引起的死锁线程都会进入BLOCKED状态,CPU资源占用不高,可以借助jstack或jconsole工具诊断。 2.内存不足 如两个线程A和B执行某个任务,A已获取10MB内存,B已获取20MB内存,它们执行都需要30MB的内存,但剩余可用的内存不够30MB了,两个线程就有可能都在等待彼此释放内存资源。 3.C/S数据交换 服务端开启某端口,等待客户端访问,客户端发送请求立即等待接收,由于某种原因服务端错过了客户端的请求,仍在等待,就会陷入双方都在等待对方发送数据。 4.数据库锁 表级别或行级别锁,比如某个线程执行for update 语句退出了事务,其他线程访问该数据库时都将陷入死锁。 5.死循环引起的死锁(系统假死) HashMap是线程不安全的,它的put方法会陷入死循环,具体原因参考 并发HashMap的put操作引起死循环 。 死循环会导致程序假死,不是真正的死锁,但某个线程对CPU消耗过多,导致其他线程等待CPU,内存等资源就也会陷入死锁等待。 来源: CSDN 作者: ziyonghong 链接: https://blog.csdn.net/ziyonghong/article

Android 子线程更新UI

≯℡__Kan透↙ 提交于 2020-03-01 22:47:26
一般情况下都认为子线程不能更新UI,这里说的子线程可以更新UI,只是为了探讨,并没有太大的使用意义,只是为了深刻认识更新UI的问题。 看下这个异常 android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 这个异常为何不是 Only the main thread that created a view hierarchy can touch its views 异常中是 original thread, 为何不是 main thread ?说明子线程是可以更新UI的 一、子线程间接更新UI 这种情况其实也是UI线程更新的,并不是真正意义上的更新UI 1、Handler 2、view.post 3、view.posDelay 4、AsyncTask 二、子线程直接更新UI 1、在onCreate中的子线程更新UI,只是钻了空子。 new Thread ( new Runnable ( ) { @Override public void run ( ) { tx . setText ( "non-UiThread update textview" ) ; } } ) . start (

Jvm 垃圾回收机制

僤鯓⒐⒋嵵緔 提交于 2020-03-01 22:47:09
判断一个对象是否可回收? 引用计数: 每当一个对象被引用时,其引用计数加一,当引用计数为0时GC回收内存将对象销毁。 缺点:无法回收互相引用的对象(互相调用其引用数永远不为0) 根可达算法 垃圾回收算法: 标记-整理算法: 适用于回收率低的区域 标记存活对象,将所有的存活对象压缩到内存的另一端。之后清理边界之外的所有空间。 复制算法:适用于回收率高的区域 将内存分为两半,每次只是用一半的内存,回收时将正在使用的内存中的存活的对象复制到另一半中,再清理内存。 在Hotsop虚拟机中的垃圾回收算法: 分代回收机制:将内存分为新生代和老年代,其中的新生代分为eden、幸存者区域(from和to),老年代(Old)。新生代:幸存者=8:1 在新生代中采用复制算法,每次只使用幸存者区域的一块,在回收时将eden和使用的一块幸存者区域存活的对象复制到另一块幸存者区域中,再清理,如果另一块幸存者区域放不下就进入老年代。 在老年代采用标记整理算法,将存活对象压缩内存的一边,清理另一边内存。 HotSpot启动回收时机: HotSpot采用根可达算法,在确定Root节点时需要停止所有线程的执行,在HotSpot中在解析代码时会将引用保存到一个OopMap数组中,以便虚拟机方便找到引用的区域。 在GC时不能有引用关系的变化,又不能频繁保存更新OopMap,HotSpot在代码中设置安全点

iOS多线程之GCD

这一生的挚爱 提交于 2020-03-01 22:46:57
1.简介 什么是GCD 全称是Grand Central Dispatch,可译为“牛逼的中枢调度器” 纯C语言,提供了非常多强大的函数 GCD的优势 GCD是苹果公司为多核的并行运算提出的解决方案 GCD会自动利用更多的CPU内核(比如双核、四核) GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程) 程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码 2.任务和队列 GCD有两个核心概念 任务:执行什么操作 队列:用来存放任务 GCD的使用有两个步骤 定制任务 确定想做的事情 将任务添加到队列中 GCD会自动将队列中的任务取出,放到对应的线程中执行 任务的取出遵循队列的FIFO原则:先进先出,后进后出 3.执行任务 GCD中有2个用来执行任务的函数 用同步的方式执行任务 dispatch_sync(dispatch_queue_t queue, dispatch_block_t block); queue:队列 block:任务 用异步的方式执行任务 dispatch_async(dispatch_queue_t queue, dispatch_block_t block); 同步和异步的区别 同步:在当前线程中执行 异步:在另一条线程中执行 4.队列的类型 并发队列 可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务) 并发功能只有在异步

HashMap线程不安全

筅森魡賤 提交于 2020-03-01 22:06:46
不要让多线程操作HashMap,否则会出现(想想多线程操作链表或数组会出现什么):数据丢失,死循环,抛出异常!!! 多线程下建议使用ConcurrentHashMap 来源: https://www.cnblogs.com/huangxiaoying/p/12392298.html

Java 并发编程:核心理论

此生再无相见时 提交于 2020-03-01 20:23:14
并发编程是Java程序员最重要的技能之一,也是最难掌握的一种技能。它要求编程者对计算机最底层的运作原理有深刻的理解,同时要求编程者逻辑清晰、思维缜密,这样才能写出高效、安全、可靠的多线程并发程序。本系列会从线程间协调的方式(wait、notify、notifyAll)、Synchronized及Volatile的本质入手,详细解释JDK为我们提供的每种并发工具和底层实现机制。在此基础上,我们会进一步分析java.util.concurrent包的工具类,包括其使用方式、实现源码及其背后的原理。本文是该系列的第一篇文章,是这系列中最核心的理论部分,之后的文章都会以此为基础来分析和解释。 一、共享性   数据共享性是线程安全的主要原因之一。如果所有的数据只是在线程内有效,那就不存在线程安全性问题,这也是我们在编程的时候经常不需要考虑线程安全的主要原因之一。但是,在多线程编程中,数据共享是不可避免的。最典型的场景是数据库中的数据,为了保证数据的一致性,我们通常需要共享同一个数据库中数据,即使是在主从的情况下,访问的也同一份数据,主从只是为了访问的效率和数据安全,而对同一份数据做的副本。我们现在,通过一个简单的示例来演示多线程下共享数据导致的问题: 代码段一: package com.paddx.test.concurrent; public class ShareData {

简述NIO,BIO的区别

大兔子大兔子 提交于 2020-03-01 20:16:37
BIO就是我们传统意义上的Inputstream,Outputstream。这个东西是同步阻塞的,效率不高,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。 NIO 随着分布式的如火如荼,为了提高访问效率,引进了NIO,同步非阻塞式IO,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器selector上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。 同时这个东西读取或者写出数据的时候不是直接操作channel的,他是操作buffer内存的。这个东西写起来很麻烦,从而诞生了Netty来封装NIO,像一些市面上牛逼的中间件用的都是这东西。比如zk.dubbo等等。。。。 好了说了这么多上代码吧,这东西到底是咋玩的呢? ////////BIO代码服务端和客户端 public class BIOClient { public static void main(String[] args) throws UnknownHostException, IOException { //要和谁进行通信,服务器IP、服务器的端口 //一台机器的端口号是有限 Socket client = new Socket("localhost", 8080