常见的线程模型

常见的线程模型

对于服务器应用而言,无论是web应用服务还是DB服务,高并发请求始终是一个绕不开的话题当有大量请求并发访问时,一定伴随着资源的不断创建和释放,导致资源利用率低,降低了服务质量。

1、单线程服务器编程模型

Redis

redis是单线程来处理命令的,所以一条命令从客户端到到服务端不会立刻被执行,所有命令都回进入到一个队列中,然后逐个执行。

Node.Js

Node.Js基于事件驱动的单线程异步编程模型

JavaScript

JavaScript是一种单线程语言,所有任务都在一个线程上完成,即采用上面的第一种方法。一旦遇到大量任务或者遇到一个耗时的任务,网页就会出现"假死",因为JavaScript停不下来,也就无法响应用户的行为。

2. 多线程服务器编程模型 

并发多个线程,每条线程并行执行不同的任务。

线程的几个主要概念

在多线程编程时,你需要了解以下几个概念:

线程同步

线程间通信

线程死锁

线程控制:挂起、停止和恢复

3、主从多线程模式

两个线程池

4、线程处理的核心数据类(阻塞队列)

(1)单线程异步编程

只要设置一个存放任务的阻塞队列,让一个工作线程每次从该队列中取出一个任务并执行,完毕再取下一个任务

(2)线程池的实现原理

生产者—消费者模式

生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产 完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者 的处理能力。

 

核心数据类型(BlockingQueue)

BlockingQueue是java.util.concurrent包中的接口,扩展了java.util中的的Queue接口。

常见的线程模型_第1张图片

在Java8的API中,这个接口有11个public方法,5/6个实现类

 

常见的线程模型_第2张图片

既然是阻塞队列,那么它核心就是阻塞和唤醒,先看看其中两个常用的实现类,以及它们之间的不同。

ArrayBlockingQueue

单锁双条件

在ArrayBlockingQueue实现中,take()和put()用的是统一的一个单锁, 对于队列“空”和“满”的情况,分别使用了两个Condition对象来维护。

常见的线程模型_第3张图片

 

数据元素是用Object[]来保存的。对于take()和put()方法,则是分别使用了takeIndex和putIndex这两个索引值来记录存放数据的位置。

常见的线程模型_第4张图片

 

Put方法

常见的线程模型_第5张图片

 

常见的线程模型_第6张图片

LinkedBlockingQueue

双锁双条件

在LinkedBlockingQueue类的实现中,是对put()和take()分别使用了两个不同的锁,都使用了ReentrantLock实现。而针对“空”和“满”的阻塞条件,也是对这两个所对象分别构建的两个Condition对象(notEmpty和notFull),构成了双锁双条件。

 

常见的线程模型_第7张图片

数据元素是node来保存的。对于take()和put()方法,则是分别使用队首node和队尾node

来取数

常见的线程模型_第8张图片

 

Put方法

常见的线程模型_第9张图片常见的线程模型_第10张图片

 

 

你可能感兴趣的:(高并发)