传统线程技术中创建线程的两种方式

传统的线程技术中有两种创建线程的方式:一是继承 类,并重写 方法;二是实现 接口,覆盖接口中的 方法,并把 接口的实现扔给 。这两种方式大部分人可能都知道,但是为什么这样玩就可以呢?下面我们来详细分析一下这两种方法的来龙去脉。 1. 揭秘Thread中run() 上面我们看到这两种方式都跟 方法有关 ... »

Java并发(9)- 从同步容器到并发容器

引言 容器是Java基础类库中使用频率最高的一部分,Java集合包中提供了大量的容器类来帮组我们简化开发,我前面的文章中对Java集合包中的关键容器进行过一个系列的分析,但这些集合类都是非线程安全的,即在多线程的环境下,都需要其他额外的手段来保证数据的正确性,最简单的就是通过synchronized ... »

Python爬虫的N种姿势

问题的由来   前几天,在微信公众号(Python爬虫及算法)上有个人问了笔者一个问题,如何利用爬虫来实现如下的需求,需要爬取的网页如下(网址为:https://www.wikidata.org/w/index.php?title=Special:WhatLinksHere/Q5 ... »

并发包下常见的同步工具类详解(CountDownLatch,CyclicBarrier,Semaphore)

[TOC] 1. 前言 在实际开发中,碰上CPU密集且执行时间非常耗时的任务,通常我们会选择将该任务进行分割,以多线程方式同时执行若干个子任务,等这些子任务都执行完后再将所得的结果进行合并。这正是著名的map reduce思想,不过map reduce通常被用在分布式计算的语境下,这里举这个例子只是 ... »

Java并发(8)- 读写锁中的性能之王:StampedLock

在上一篇《你真的懂ReentrantReadWriteLock吗?》中我给大家留了一个引子,一个更高效同时可以避免写饥饿的读写锁 StampedLock。StampedLock实现了不仅多个读不互相阻塞,同时在读操作时不会阻塞写操作。 为什么StampedLock这么神奇?能够达到这种效果,它的核心 ... »

并发请求 + 事务嵌套 + 更新数据 = 死锁

今有幸为同事排查死锁问题。 问题描述:一个get接口,内依据参数执行select ... for update,未考虑并发场景,导致程序死锁,且只要并发请求该接口,几乎百发百中。 问题定位: 1.检测数据库死锁情况,结果无。 2.接口内无相关共享资源,不会死锁 3.由于从事许久事务方面工作,所以想到 ... »

IO多路复用(一)-- Select、Poll、Epoll

在上一篇博文中提到了五种IO模型,关于这五种IO模型可以参考博文 "IO模型浅析 阻塞、非阻塞、IO复用、信号驱动、异步IO、同步IO" ,本篇主要介绍IO多路复用的使用和编程。 IO多路复用的概念 多路复用是一种机制,可以用来监听多种描述符,如果其中任意一个描述符处于就绪的状态,就会返回消息给对应 ... »

Java并发之线程池ThreadPoolExecutor源码分析学习

线程池学习 以下所有内容以及源码分析都是基于JDK1.8的,请知悉。 我写博客就真的比较没有顺序了,这可能跟我的学习方式有关,我自己也觉得这样挺不好的,但是没办法说服自己去改变,所以也只能这样想到什么学什么了。 ​ 池化技术真的是一门在我看来非常牛逼的技术,因为它做到了在有限资源内实现了资源利用的最 ... »

「造个轮子」——cicada 源码分析

两天前写了文章《「造个轮子」——cicada(轻量级 WEB 框架)》 向大家介绍了 cicada 之后收到很多反馈,也有许多不错的建议。 同时在 GitHub 也收获了 80 几颗 小♥♥(绝对不是刷的。。) ... »

Java并发(6)- CountDownLatch、Semaphore与AQS

引言 上一篇文章中详细分析了基于AQS的ReentrantLock原理,ReentrantLock通过AQS中的state变量0和1之间的转换代表了独占锁。那么可以思考一下,当state变量大于1时代表了什么?J.U.C中是否有基于AQS的这种实现呢?如果有,那他们都是怎么实现的呢?这些疑问通过详细 ... »

基于双向链表实现无锁队列的正确姿势(对之前博客中错误的修正)

[TOC] 1. 前言 如果你认真看过我前几天写的这篇博客 "自己动手构建无锁的并发容器(栈和队列)" 的队列部分,那么我要向你表示道歉。因为在实现队列的出队方法时我犯了一个低级错误:队列的出队方向是在队列头部,而我的实现是在队列尾部。尽管代码能够正确执行,但明显不符合队列规范。所以那部分代码写作" ... »

自己动手构建无锁的并发容器(续篇)——基于单链表实现的无锁队列

1. 前言 在 "自己动手构建无锁的并发容器(栈和队列)" 中我们基于CAS算法构建了自己的无锁队列,其底层实现是不带哨兵结点的双向链表。双向链表为当前结点保留了指向前驱结点的引用,这种特性有时很有用,比如AQS中线程被唤醒后会通过prev指针找到前驱结点,通过判断其是否是头结点来决定是否要获取锁。 ... »

从源码角度彻底理解ReentrantLock(重入锁)

[TOC] 1.前言 在 "ReentrantLock(重入锁)功能详解和应用演示" 这篇文章里我们讲解并演示了ReentrantLock(重入锁)的各种功能,其中就谈到ReentrantLock可以有公平锁和非公平锁的不同实现,只要在构造它的时候传入不同的布尔值,继续跟进下源码我们就能发现,关键在 ... »

秒杀架构实践

之前在 Java-Interview 中提到过秒杀架构的设计,这次基于其中的理论简单实现了一下。 本次采用循序渐进的方式逐步提高性能达到并发秒杀的效果,文章较长请准备好瓜子板凳(liushuizhang »

Java并发(2)- 聊聊happens-before

引言 上一篇文章聊到了Java内存模型,在其中我们说JMM是建立在happens before(先行发生)原则之上的。 为什么这么说呢?因为在Java程序的执行过程中,编译器和处理器对我们所写的代码进行了一系列的优化来提高程序的执行效率。这其中就包括对指令的“重排序”。 重排序导致了我们代码并不会按 ... »

golang基础--Gocurrency并发

goroutine只是由官方实现的超级"线程池"而已,每个实例4 5kb的栈内存占用和用于实现机制而大幅减少的创建和销毁开销。 并发不是并行(多CPU): 并发主要由切换时间片来实现"同时"运行,并行则是直接利用多核实现多线程的运行,但Go可以设置使用核数,以发挥多核计算机的能力。 通过go关键字实 ... »

你应该知道的 volatile 关键字

前言不管是在面试还是实际开发中 volatile 都是一个应该掌握的技能。 首先来看看为什么会出现这个关键字。 内存可见性由于 Java 内存模型(JMM)规定,所有的变量都存放在主内存中,而每个线程都有着自己的工作内存(高速缓存)。 线程在工作时,需要将主内存中的数据拷贝到工作内存中。这样对数据的... ... »

何以解我那心中对长连接的惧?

与高人沟通,是最好的成长,解我那心中对长连接的惧! 一直以来,我对长连接都是怀着深深地恐惧。因为在我的印象中,如果每个用户都保持长连接,那么,假设有稀稀松松有几个用户来到你的服务面前,那么你的并发瞬间就飚高了,那么你的服务能力一下就下去了。所以,我害怕,害怕啥事没干,服务就被干垮了! 长连接与短连接 ... »