线程阻塞

java并发神器 AQS(AbstractQueuedSynchronizer)

余生颓废 提交于 2020-03-21 22:27:01
3 月,跳不动了?>>> AbstractQueuedSynchronizer AQS的全称为(AbstractQueuedSynchronizer),这个类在java.util.concurrent.locks包 AQS的核心思想 是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并将共享资源设置为锁定状态,如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制AQS是用CLH队列锁实现的,即将暂时获取不到锁的线程加入到队列中。 CLH(Craig,Landin,and Hagersten)队列是一个虚拟的双向队列,虚拟的双向队列即不存在队列实例,仅存在节点之间的关联关系。 用大白话来说,AQS就是基于CLH队列,用volatile修饰共享变量state,线程通过CAS去改变状态符,成功则获取锁成功,失败则进入等待队列,等待被唤醒。 CAS(Compare and Swap) 科普 ​ 如字面意思,就是先比较再替换, ​ cas方法有三个重要参数 : 待比较的值、预期值、要修改的新值, 如果预期值是待比较的值一致,那么就把 要修改的值赋值给待比较的值 ​ 伪代码如下: Object old; // 待比较的值 Object new; // 预期值 Object update;// 要修改的新值 if(old == new)

Java 线程的基本使用

六眼飞鱼酱① 提交于 2020-03-21 20:36:11
线程的2种实现方式 1、继承Thread类,重写run()方法 public class Thread1 extends Thread{ @Override public void run() { //要执行的代码 while (true){ System.out.println("thread1 is running...."); } } } Thread1 thread1 = new Thread1(); thread1.start(); 2、实现Runnable接口 public class MyRunnable implements Runnable{ @Override public void run() { //要执行的代码 while (true) { System.out.println("thread2 is running...."); } } } MyRunnable myRunnable = new MyRunnable(); Thread thread2 = new Thread(myRunnable); thread2.start(); 相比而言,第一种要简单些。 我们测试下: public class Test { public static void main(String[] args) { Thread1 thread1 = new

python队列基本使用

半世苍凉 提交于 2020-03-21 19:59:28
Python queue队列 作用:    解耦:使程序直接实现松耦合,修改一个函数,不会有串联关系。    提高处理效率:FIFO = 现进先出,LIFO = 后入先出。 队列:   队列可以并发的派多个线程,对排列的线程处理,并切每个需要处理线程只需要将请求的数据放入队列容器的内存中,线程不需要等待,当排列完毕处理完数据后,线程在准时来取数据即可。请求数据的线程只与这个队列容器存在关系,处理数据的线程down掉不会影响到请求数据的线程,队列会派给其他线程处理这分数据,它实现了解耦,提高效率。队列内会有一个有顺序的容器,列表与这个容器是有区别的,列表中数据虽然是排列的,但数据被取走后还会保留,而队列中这个容器的数据被取后将不会保留。当必须在多个线程之间安全地交换信息时,队列在线程编程中特别有用。 Python四种类型的队例: Queue:FIFO 即first in first out 先进先出 LifoQueue:LIFO 即last in first out 后进先出 PriorityQueue:优先队列,级别越低,越优先deque:双边队列 导入三种队列,包 from queue import Queue,LifoQueue,PriorityQueue Queue 先进先出队列: #基本FIFO队列 先进先出 FIFO即First in First Out,先进先出

一个自旋锁的栗子

大兔子大兔子 提交于 2020-03-21 17:27:13
  一直以来不是怎么清楚自旋锁,最近有点时间,好好的学习了一下;   所谓的自旋锁在我的理解就是多个线程在尝试获取锁的时候,其中一个线程获取锁之后,其他的线程都处在一直尝试获取锁的状态,不会阻塞!!!那么什么叫做一直尝试获取锁呢?就是一个循环,比较经典的是AtomicInteger中的一个updateAndGet方法,下图所示(当然也可以直接看unsafe类中的getAndAddInt等类似方法);   我们可以看出在while循环中使用CAS去尝试更新一个变量,如果更新失败,就会一直在这个循环中一直在尝试;成功的话,就可以到最后的return语句;   由此我们可以大概知道如果自旋的线程过多,那么CPU的资源就会被大量消耗!!!   顺便提一个东西叫做原子引用,官方提供了AtomicInteger,AtomicBoolean等原子类,那么如果我们自己定义的类也需要有原子性怎么办呢?所以官方提供了一个AtomicReference类,可以将我们自己定义的类封装一下,就成了我们自己的原子类,例如AtomicReference<Student> atomicReference = new AtomicReference<>();,然后我们对Student的实例进行CAS各种CAS操作;   栗子: package TestMain; import lombok.extern.slf4j

CountDownLatch,CyclicBarrier,Semaphore

送分小仙女□ 提交于 2020-03-21 15:25:06
CountDownLatch是倒数,doneSignal = new CountDownLatch(LATCH_SIZE);赋初值后,在主线程中等待doneSignal.await();其它线程中,每完成一个就减一doneSignal.countDown();减到0时主线程继续。 CyclicBarrier是正数,cb = new CyclicBarrier(SIZE);主线程中开启各子线程,子线程调用cb.await()进行等待;cb计数count会加一,等于SIZE时会继续所有等待线程。 Semaphore是信号灯,Semaphore sem = new Semaphore(SEM_MAX);主线程中开启各子线程,子线程调用sem.acquire(count);每调用一次,sem计数会减相应数值,减为0时其它线程再调用acquire时会阻塞,线程结束后记得要sem.release(count); CountDownLatch和Semaphore用的是共享锁,而CyclicBarrier是独占锁。 CountDownLatch只能赋值一次,而CyclicBarrier可赋值多次。 概要 前面对" 独占锁 "和" 共享锁 "有了个大致的了解;本章,我们对CountDownLatch进行学习。 和ReadWriteLock.ReadLock一样

浅析 Node.js 单线程模型

江枫思渺然 提交于 2020-03-21 10:24:47
总结笔记:对于每个用户请求,由主线程接收并存放于一个事件队列中(不做任何处理),当无请求发生时,即主线程空闲,主线程开始循环处理事件队列中的任务: 对于非阻塞JS程序: 1、若某事件需要I/O操作,则主线程发出I/O请求,然后继续执行,由底层的程序实现I/O并返回I/O数据(底层程序是多线程的,JS是单线程的),底层I/O线程处理完后将该事件重新放入事件队列并释放当前线程; 2、某事件不需要I/O操作,则主线程直接处理;(由其他线程处理后放入的事件此时也被主线程直接处理掉); 对于阻塞JS程序: 1、若某事件需要I/O操作,则主线程发出I/O请求,然后等待I/O结束,由底层的程序实现I/O并返回I/O数据,主线程获得该事件所需数据后继续处理该事件; 2、某事件不需要I/O操作,则主线程直接处理; 综上可知,node.js由js解释程序和底层代码实现,JS代码是主线程,是单线程执行,而底层代码是多线程,可同时处理多个I/O请求,js中的阻塞与非阻塞代码只决定js在I/O时继不继续执行(当然,若阻塞执行,底层多线程也没啥用了),而底层会为每一个I/O请求创建一个线程; 注意:这只是对Node.js的一个分析,用来理解nodejs的线程模型而已,实际使用要具体问题具体分析,建议结合http://www.runoob.com/nodejs/nodejs-callback

计算Java对象内存大小

这一生的挚爱 提交于 2020-03-21 07:05:18
摘要 本文以如何计算Java对象占用内存大小为切入点,在讨论计算Java对象占用堆内存大小的方法的基础上,详细讨论了Java对象头格式并结合JDK源码对对象头中的协议字段做了介绍,涉及内存模型、锁原理、分代GC、OOP-Klass模型等内容。最后推荐JDK自带的Hotspot Debug工具——HSDB,来查看对象在内存中的具体存在形式,以论证文中所述内容。 背景 目前我们系统的业务代码中大量使用了LocalCache的方式做本地缓存,而且cache的maxSize通常设的比较大,比如10000。我们的业务系统中就使用了size为10000的15个本地缓存,所以最坏情况下将可缓存15万个对象。这会消耗掉不菲的本地堆内存,而至于实际上到底应该设多大容量的缓存、运行时这大量的本地缓存会给堆内存带来多少压力,实际占用多少内存大小,会不会有较高的缓存穿透风险,目前并不方便知悉。考虑到对缓存实际占用内存的大小能有个更直观和量化的参考,需要对运行时指定对象的内存占用进行评估和计算。 要计算Java对象占用内存的大小,首先需要了解Java对象在内存中的实际存储方式和存储格式。 另一方面,大家都了解Java对象的存储总得来说会占用JVM内存的堆内存、栈内存及方法区,但由于栈内存中存放的数据可以看做是运行时的临时数据,主要表现为本地变量、操作数、对象引用地址等。这些数据会在方法执行结束后立即回收掉

HttpClient 教程 (二)

无人久伴 提交于 2020-03-20 23:48:07
第二章 连接管理 HttpClient有一个对连接初始化和终止,还有在活动连接上I/O操作的完整控制。而连接操作的很多方面可以使用一些参数来控制。 2.1 连接参数 这些参数可以影响连接操作: 'http.socket.timeout': 定义了套接字的毫秒级超时时间(SO_TIMEOUT),这就是等待数据,换句话说,在两个连续的数据包之间最大的闲置时间。如果超时时间是0就解释为是 一个无限大的超时时间。这个参数期望得到一个java.lang.Integer类型的值。如果这个参数没有被设置,那么读取操作就不会超时(无限大的超 时时间)。 'http.tcp.nodelay': 决定了是否使用Nagle算法。Nagle算法视图通过最小化发送的分组数量来节省带宽。当应用程序希望降低网络延迟并提高性能时,它们可以关闭 Nagle算法(也就是开启TCP_NODELAY)。数据将会更早发送,增加了带宽消耗的成文。这个参数期望得到一个 java.lang.Boolean类型的值。如果这个参数没有被设置,那么TCP_NODELAY就会开启(无延迟)。 'http.socket.buffer- size':决定了内部套接字缓冲使用的大小,来缓冲数据同时接收/传输HTTP报文。这个参数期望得到一个java.lang.Integer类型的 值。如果这个参数没有被设置

HttpClient 教程 (二)

纵饮孤独 提交于 2020-03-20 23:47:50
第二章 连接管理 HttpClient有一个对连接初始化和终止,还有在活动连接上I/O操作的完整控制。而连接操作的很多方面可以使用一些参数来控制。 2.1 连接参数 这些参数可以影响连接操作: 'http.socket.timeout':定义了套接字的毫秒级超时时间(SO_TIMEOUT),这就是等待数据,换句话说,在两个连续的数据包之间最大的闲置时间。如果超时时间是0就解释为是一个无限大的超时时间。这个参数期望得到一个java.lang.Integer类型的值。如果这个参数没有被设置,那么读取操作就不会超时(无限大的超时时间)。 'http.tcp.nodelay':决定了是否使用Nagle算法。Nagle算法视图通过最小化发送的分组数量来节省带宽。当应用程序希望降低网络延迟并提高性能时,它们可以关闭Nagle算法(也就是开启TCP_NODELAY)。数据将会更早发送,增加了带宽消耗的成文。这个参数期望得到一个java.lang.Boolean类型的值。如果这个参数没有被设置,那么TCP_NODELAY就会开启(无延迟)。 'http.socket.buffer-size':决定了内部套接字缓冲使用的大小,来缓冲数据同时接收/传输HTTP报文。这个参数期望得到一个java.lang.Integer类型的值。如果这个参数没有被设置

HttpClient 教程 (二)

ⅰ亾dé卋堺 提交于 2020-03-20 23:47:05
第二章 连接管理 HttpClient有一个对连接初始化和终止,还有在活动连接上I/O操作的完整控制。而连接操作的很多方面可以使用一些参数来控制。 2.1 连接参数 这些参数可以影响连接操作: 'http.socket.timeout':定义了套接字的毫秒级超时时间(SO_TIMEOUT),这就是等待数据,换句话说,在两个连续的数据包之间最大的闲置时间。如果超时时间是0就解释为是一个无限大的超时时间。这个参数期望得到一个java.lang.Integer类型的值。如果这个参数没有被设置,那么读取操作就不会超时(无限大的超时时间)。 'http.tcp.nodelay':决定了是否使用Nagle算法。Nagle算法视图通过最小化发送的分组数量来节省带宽。当应用程序希望降低网络延迟并提高性能时,它们可以关闭Nagle算法(也就是开启TCP_NODELAY)。数据将会更早发送,增加了带宽消耗的成文。这个参数期望得到一个java.lang.Boolean类型的值。如果这个参数没有被设置,那么TCP_NODELAY就会开启(无延迟)。 'http.socket.buffer-size':决定了内部套接字缓冲使用的大小,来缓冲数据同时接收/传输HTTP报文。这个参数期望得到一个java.lang.Integer类型的值。如果这个参数没有被设置