java的7种阻塞队列及其实现原理-编程思维
队列和阻塞队列 队列 队列(Queue)是一种经常使用的集合。Queue 实际上是实现了一个先进先出(FIFO:First In First Out)的有序表。和 List、Set 一样都继承自 Collection。它和 List 的区别在于,List可以在任意位置添加和删除元素,而Queue 只有两个操作: 把元素添加到队列末尾; 从队列头部取出元素。 超市的收银台就是一个队列: 我
morethink program
队列和阻塞队列 队列 队列(Queue)是一种经常使用的集合。Queue 实际上是实现了一个先进先出(FIFO:First In First Out)的有序表。和 List、Set 一样都继承自 Collection。它和 List 的区别在于,List可以在任意位置添加和删除元素,而Queue 只有两个操作: 把元素添加到队列末尾; 从队列头部取出元素。 超市的收银台就是一个队列: 我
记录之前的一次优化过程,之前发布在wiki上,现摘出发布。 0.前言 主要查询表为还款计划表xx_plan(近4000w,日新增10~20w)、实还记录表xx_actual(2600w+,日新增5~10w)、代偿记录表xx_compensation(近200w,日新增1w)。目前查询超时原因主要是表数据量过千万,且指标很多需要关联查询才能获得(数据查询SQL关键词:left join, coun
我们都知道在Java编程中多线程的同步使用synchronized关键字来标识,那么这个关键字在JVM底层到底是如何实现的呢。 我们先来思考一下如果我们自己实现的一个锁该怎么做呢: 首先肯定要有个标记记录对象是否已经上锁,执行同步代码之前判断这个标志,如果对象已经上锁线程就阻塞等待锁的释放。 其次要有一个结构体来维护这些等待中的线程,锁释放后来遍历这些线程让他们去抢锁。 第一点Java使用对
在介绍Java内存模型之前,先来了解一下为什么要有内存模型,以及内存模型是什么。然后我们基于对内存模型的了解,学习Java内存模型以及并发编程的三大特性。 为什么要有内存模型 在计算机中,所有的运算操作都是由CPU的寄存器来完成的,CPU指令的执行需要涉及到数据的读写操作,而CPU只能访问主存中的数据。随着技术的发展,CPU的执行速度越来越快,而内存的访问速度没有太大的变化,导致CU
进程和线程 说到多线程,必然绕不开进程与线程的概念及区别。 对于计算机而言,当前的操作系统可以同时运行多个应用程序,而每一个应用程序就是一个进程(Process),它拥有自己独立的内存空间。线程是进程中的一个执行流程,是执行任务的最小单位。一个进程内部允许同时启动多个线程(Thread),同时执行多个任务。线程是轻量级的进程,它负责在单个程序里执行多任务,通常由操作系统负责多个线程的调度
在前面一篇介绍了线程的生命周期【并发编程之多线程概念 】,在本篇将正式介绍如何创建、中断线程,以及线程是如何销毁的。最后,我们会讲解一些常见的线程API。 线程创建 Java 5 以前,实现线程有两种方式:扩展java.lang.Thread类,实现java.lang.Runnable接口。这两种方式都是都是直接创建线程,而每次new Thread都会消耗比较大的资源,导致每次新建对
本文主要讨论线程的各种属性,包括:主线程、线程优先级、守护线程、线程组、处理未捕获异常的处理器。 主线程 任何一个Java程序启动时,至少会启动一个线程执行main方法,这个线程就被称为主线程(Main Thread)。它是产生其它线程的线程,即:其它所有线程的主线程的子孙线程。通常,主线程都是最后结束的,因为它要执行其它子线程的关闭工作。 线程优先级 计算机只有
产生死锁的4个必要条件 互斥条件:在一段时间内某资源仅为一个线程所占有 不可剥夺条件:线程所获得的资源在未使用完毕之前,不能被其他线程强行夺走 请求和保持条件:线程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其他线程占有 循环等待条件:存在一种线程资源的循环等待链,链中每一个线程已获得的资源同时被链中下一个线程所请求。 产生死锁的情况 多个锁的交叉
并发编程主要设计两个关键字:一个是synchronized,另一个是volatile。下面主要讲解这两个关键字,并对这两个关机进行比较。 synchronized Monitor对象 每一个对象都与一个Monitor相关联,一个monitor的lock在某一刻只能被一个线程获取。【排他性】 monitor有一个计数器,当为0时,该monitor的lock未被获取;当有线程持获取
并发 很多程序员应该对并发一词并不陌生,并发如同一把双刃剑,如果使用得当,可以帮助我们更好的压榨硬件的性能,反之,也会产生一些难以排查的问题。这里,先简单介绍下并发的几个基本概念。 进程与线程 进程:进程是操作系统进行资源分配和调度的基本单位。 线程:线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。 上面是百度百科对进程和线程的解释,可能有点抽象,这里笔者再
并发的优势与风险 优势 速度:同时处理多个请求,响应更快;复杂的操作可以同时分成多个进程或者线程同时进行。 设计:程序设计在某些情况下变得更简单。 资源利用:CPU可以在等待IO的时候做其他的事情。 风险 安全性:多个线程同时读写数据可能会产生于期望不相符的结果。 活跃性:某个操作无法进行下去时,就会发生活跃性问题。比如:死锁、饥饿、活锁等问题。 死锁:两个或多个线程在执行时互相持有对方所需要
volatile原理 Java虚拟机规范中定义了Java内存模型(Java Memory Model,即JMM)来屏蔽掉各种硬件和操作系统的内存访问差异,以实现Java程序在各个平台下都能达到一致的并发效果。 Java内存模型中规定所有的变量都存储在主内存,每个线程都有自己独立的工作内存,线程的工作内存中保存了该线程所需要用到的本地变量,以及从主内存中拷贝到工作内存的副本。线程对于变量的读、写都
线程池 假设我们编写了一个Servlet应用,当用户通过浏览器发起一个请求到达我们服务器时,传统的Servlet应用一般针对一个用户请求创建一个线程去执行请求,等到请求执行完毕后,再销毁线程。这种设计在用户量几百或者几千的情况下一般不会有什么大问题,但是如果我们的用户量上达几万甚至几十万几百万,频繁的创建、销毁线程,将会给服务器带来巨大的开销,甚至会出现OOM(Out Of Memory)异常。
1.Await为什么不会导致堵塞 我们都知道Await关键字是.Net FrameWork4.5引入的特性。await使得我们使用异步更加时特别便捷,并且还不会导致线程堵塞。我们在使用时也就莫名其妙的使用。往往不知道为什么不会导致线程堵塞。在这里,简单的谈论下await的一点原理。 在c#并行编程这本书中是这么介绍await的:async方法在开始时以同步方式执行,在
在执行一系列带有IO操作(例如下载文件),且互不相关的异步任务时,采用多线程可以很极大的提高运行效率。线程池包含了一系列的线程,并且可以管理这些线程。例如:创建线程,销毁线程等。本文将介绍如何使用Java中的线程池执行任务。 1. 任务类型 在使用线程池执行任务之前,我们弄清楚什么任务可以被线程池调用。按照任务是否有返回值可以将任务分为两种,分别是实现Runnable的任务类(无参数无返回值)和
在研究Executors提供的线程池时自然会想到标题这个问题,既然已经有了newFixedThreadPool,为什么还要存在newSingleThreadExecutor这个方法。难道newFixedThreadPool(1)不是只有一个线程(Single Thread)的?本文将通过分析JDK中的相关源码回答这个问题。 源码分析 写JDK代码的大佬们早就预料到了我们会有此疑问,在newSin
非阻塞套接字和IO模型 非阻塞套接字: 防止进入阻塞状态,程序停滞。如recv、accept、input都会阻塞。 socket.socket()生成一个套接字用于监听;server.accept()生成一个套接字用于收发信息;两者都要设置非阻塞 1 import socket 2 3 server = socket.socket() 4 server.setblockin
多进程、多线程在不同环境下的操作 多进程:Linux创建进程是操作系统把父进程的东西拷贝到子进程 Windows创建进程类似于模块导入 Linux环境下开启多进程,可以用os里的fork 1 import os 2 import time 3 pid = os.fork() 4 5 if pid == 0: # 子进程永远返回0 6 print('子进程{}
进程通信和线程通信 进程间通信: 进程是拥有独立空间的,如果开多个进程对某个数据进行处理,由于进程是独立空间,那么两个进程如何通信拥有共同 空间呢?我们可以在父进程里启动一个服务器进程开辟一个公共空间。开启之后在子进程处理数据,父进程也会出现相应的 效果。Manager 是专门用来做共享的! 1 from multiprocessing import Process, Manager
可重复利用的线程 1 import threading 2 import queue 3 4 5 class MyThread(threading.Thread): 6 7 def __init__(self): 8 super().__init__() 9 self.queue = queue.Queue() 10