目录
一、线程池
(1)概念:是一组已经初始化并等待执行任务的线程集合。 通过使用线程池,我们可以避免频繁地创建和销毁线程,从而节省资源和减少系统开销。线程池的核心思想是通过复用线程来提高性能。
<1>corePoolSize:核心线程数量
<2>maximumPoolSize:最大线程数量=核心线程数+临时线程数
<3>keepAliveTime:空闲时间的数值
<4>unit:空闲时间的单位,背后实现的数据结构是枚举
<5>workQueue:传递任务的阻塞队列
<6>threadFactory:创建线程的⼯⼚,参与具体的创建线程⼯作.通过不同线程⼯⼚创建出的线程相当于 对⼀些属性进⾏了不同的初始化设置。
<7>handler:拒绝策略,如果任务量超出公司的负荷了接下来怎么处理->
AbortPolicy():超过负荷,抛出异常
CallerRunsPolicy():由调用者来处理多的线程
DiscardOldestPolicy():如果队列上限,放弃最早的任务,来处理新的线程。
DiscardPolicy():丢掉多出来的线程。
(2)实现线程池:由于ThreadPoolExecutor功能强大,使用麻烦。所以标准库进一步对这一类进行封装,Executors提供了一些工厂方法,可以更方便的创建出线程池。
CachedThreadPool():设置了非常大的线程数,就可以对线程池不停的扩容。
FixedThreadPool():同时设置核心线程数和最大线程数,固定数量不会自动扩容。还有SingleThreadExecutor()、ScheduledThreadPool()、WorkStealingPool()等常用方法。
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Demo22 {
public static void main(String[] args) throws InterruptedException {
ExecutorService pool = Executors.newFixedThreadPool(4);
for (int i = 0; i <100 ; i++) {
int id = i;
pool.submit(()->{
Thread current = Thread.currentThread();
System.out.println("hello"+ id +","+current.getName());
});
}
Thread.sleep(2000);
pool.shutdown();
}
}
二、阻塞队列的概念
阻塞队列是⼀种特殊的队列.也遵守"先进先出"的原则. 阻塞队列能是⼀种线程安全的数据结构,并且具有以下特性:
<1>当队列满的时候,继续⼊队列就会阻塞,直到有其他线程从队列中取⾛元素.
<2>当队列空的时候,继续出队列也会阻塞,直到有其他线程往队列中插⼊元素.
阻塞队列的⼀个典型应⽤场景就是"⽣产者消费者模型".这是⼀种⾮常典型的开发模型
三、消费者模型
(1)概念:⽣产者消费者模式就是通过⼀个容器来解决⽣产者和消费者的强耦合问题。 ⽣产者和消费者彼此之间不直接通讯,⽽通过阻塞队列来进⾏通讯,所以⽣产者⽣产完数据之后不⽤ 等待消费者处理,直接扔给阻塞队列,消费者不找⽣产者要数据,⽽是直接从阻塞队列⾥取。
(2)阻塞队列与模型的关系:阻塞队列相当于一个缓冲区,可以削峰填谷,使两个服务器之间的解“耦合”。
四、Java中标准库中的堵塞队列
(1)BlockingQueue:
BlockingQueue是一个接口,接口不能实例化,所以Java中实现BlockingQueue接口的是他的子类。put用于阻塞式的入列队,take用于阻塞式的出列队。BlockingQueue也有offer,poll,peek等方法,但是这些方法不带有阻塞性。
五、自实现阻塞队列
阻塞队列通过“循环队列”的方式实现,在进行put,take需要原子性的方法的时候,用synchronized来进行加锁打包,put插入元素的时候,如果队列满了用wait进行堵塞,等待take唤醒(注意,要在循环中进⾏wait.被唤醒时不⼀定 队列就不满了,因为同时可能是唤醒了多个线程).。take取出元素的时候,如果队列空了,则用wait进行堵塞,等待put唤醒。
class MyBlokingQueue{
public int head = 0;
public int tail = 0;
public int size = 0;
public String[] data = null;
public MyBlokingQueue(int i){
data = new String[i];
}
public String take () throws InterruptedException {
String take ="";
synchronized (this){
if(size == 0){
this.wait();
}
take = data[head];
head++;
if(head >= data.length){
head = 0;
}
size--;
this.notify();
}
return take;
}
public void put(String s) throws InterruptedException {
synchronized (this){
if(size == data.length){
this.wait();
}
data[tail] =s;
tail++;
if(tail >= data.length){
tail = 0;
}
size++;
this.notify();
}
}
}
}