java多线程高级教程,这些你都懂了吗?

一、countdownLatch和cyclicbarrier(这两个做多线程控制很好用,工作中会经常用到)

countdownLatch:主线程阻塞,当多个线程countdown到0,主线程执行;

cyclicbarrier:多个线程等待,当都处于等待状态了一起执行(类似于赛跑机制)

countdownLatch

cyclicbarrier

二、volatile和threadlocal

这两个也要很好掌握,不仅常用,而且面试时候也经常问到!

volatile:使属性可见性。有个属性是共享属性,这个关键字会在每个线程内开一块内存,每次子线程都会从主线程拿最新的属性放到内存中。但是有个问题,他只是拿最新的,比如:计数器,每个线程都执行+1操作。一个线程+1,另外两个同时读取这个属性,那么不会加2次,而是只加一次,这就是valatile不能保证原子性的原因。

threadlocal:用于做方法外的全局属性。这个跟volatile刚好相反,使全局变量独立,每个线程里都有一份独立副本。

这是hibernate的源码,如果当前线程没有session就openSession放到ThreadLocalMap中,每个线程的session都是独立的不会相互受影响。

三、AtomicInteger:支持原子性计数器。

之前说volatile不能作为计数器,那么多线程计数器要用atomic类的AtomicInteger

四、并发类容器

ConCurrentHashMap、CopyAndWriteArrayList、CopyAndWriteArraySet。

ConCurrentHashMap(底层分成16个hashtable来保证并发)读支持高并发读,写和删除时候只支持16个线程,所以一般也要上锁; copyandwrite支持高并发读,写的话要加锁(原理是,写的时候赋值一个容器,写好了把指针指向新容器并且删除原容器)

map、list、set都有并发类容器。面试时候经常会问hashmap和ConCurrentHashMap区别。这个demo我就不写了,用法和我们平时用的集合都一样,只是他们不会造成线程不安全。

五、并发类队列

阻塞的意思是,当达到队列最大容量或者为空,线程还往里加东西或取东西会被阻塞;有界意思,可以设置队列大小。

(非阻塞队列)ConcurrentLinkedQueue无阻塞无界限队列(高并发性能最好,peek取出不删除,poll取出删除),

(阻塞队列)ArrayBlockingQueue阻塞有界队列,LinkBlockingQueue阻塞无界队列(生产者消费者首选,take方法会阻塞,poll方法没有就返回null)。

这里我们以最经典的生产者消费者模式作为例子

这里我们顺便做一个延伸,我们用的所有线程池,包括面试时候经常问的要你自定义一个线程池怎么做?我们先看一下线程池的源码。

也就是说线程池也是用并发队列作为线程的容器。我们自定义时候也只需要重现实例化ThreadPoolExcutor,设置我们自己需要的参数即可。

六、分布式锁

这个其实已经不属于java代码范畴,但是我上一篇讲基础的时候,一些兄弟说我说的太简单,另一些又说太难,所以我加了一个分布式锁,希望能满足更多人需求。

分布式锁,主要用在分布式集群上,既然是分布式,那就有多个jvm,即使你代码写出花来也不能控制。所以只有一个办法就是借助第三方工具。比如memcache、redis、zk

1. 首先明确一点,有人可能会问是否可以考虑采用ReentrantLock来实现,但是实际上去实现的时候是有问题的,ReentrantLock的lock和unlock要求必须是在同一线程进行,而分布式应用中,lock和unlock是两次不相关的请求,因此肯定不是同一线程,因此导致无法使用ReentrantLock。

2. 基于数据库表做乐观锁,用于分布式锁。

3. 使用memcached的add()方法,用于分布式锁。

4. 使用memcached的cas()方法,用于分布式锁。(不常用)

5. 使用redis的setnx()、expire()方法,用于分布式锁。

6. 使用redis的setnx()、get()、getset()方法,用于分布式锁。(本人最常用的也是唯一用的方法)

7. 使用redis的watch、multi、exec命令,用于分布式锁。(不常用)

8. 使用zookeeper,用于分布式锁。(不常用)

这个我就不举demo了,不然太多了

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Golang语言社区

Go web之旅(路由篇)

据说Go语言设计出来就是为了解决web软件的并发等诸多问题的,所以Go语言又被称为互联网中的c语言。一般的web应用采用的是"请求-响应"模式。在Go web中...

3619
来自专栏Linux驱动

第4阶段——制作根文件系统之分析init进程(2)

本节目标: (1) 了解busybox(init进程和命令都放在busybox中) (2) 创建SI工程,分析busybox源码来知道init进程做了哪些事情 ...

2489
来自专栏区块链

如何基于Python写一个TCP反向连接后门

0x0 介绍 在Linux系统做未授权测试,我们须准备一个安全的渗透环境,通常第一件事就是安装虚拟机。且在攻击阶段中还需要对受害系统进行控制。常见的后门大多数是...

3157
来自专栏Java技术栈

单点登录终极方案之 CAS 应用及原理

Cookie的单点登录的实现方式很简单,但是也问题颇多。例如:用户名密码不停传送,增加了被盗号的可能。另外,不能跨域!

2382
来自专栏腾讯云TStack专栏

对象存储,了解一下

? 对象存储,通常指 S3 (Simple Storage Service) 服务,由AWS提供公有云服务,而 Ceph 也可以提供兼容 S3 协议的对象存储...

6122
来自专栏用户2442861的专栏

HTTP POST GET 本质区别详解

    一般在浏览器中输入网址访问资源都是通过GET方式;在FORM提交中,可以通过Method指定提交方式为GET或者POST,默认为GET提交

2511
来自专栏用户2442861的专栏

Visual Stdio的中的dll和lib

http://blog.csdn.net/dodomouse/article/details/12843821

661
来自专栏DOTNET

【翻译】MongoDB指南/CRUD操作(三)

【原文地址】https://docs.mongodb.com/manual/ CRUD操作(三) 主要内容: 原子性和事务(Atomicity and Tran...

2909
来自专栏散尽浮华

nginx负载均衡(5种方式)、rewrite重写规则及多server反代配置梳理

Nginx除了可以用作web服务器外,他还可以用来做高性能的反向代理服务器,它能提供稳定高效的负载均衡解决方案。nginx可以用轮询、IP哈希、URL哈希等方式...

6626
来自专栏Laoqi's Linux运维专列

Linux入门到精pao通lu

2514

扫码关注云+社区