当前位置: 首页 > news >正文

Java--多线程知识(四)

一.生产者消费者模型

创建两个线程 t1,t2。 再创建一个阻塞队列,通过阻塞队列连接t1,t2。

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;public class Demo1 {public static void main(String[] args) {//阻塞队列BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(100);//生产者Thread t1 = new Thread(()->{int n = 0;while (true){System.out.println("生产了:" + n);try {queue.put(n);} catch (InterruptedException e) {throw new RuntimeException(e);}n++;}});//消费者Thread t2 = new Thread(()->{while ( true){try {int n = queue.take();System.out.println("消费了:" + n);} catch (InterruptedException e) {throw new RuntimeException(e);}}});t1.start();t2.start();}
}

以上代码是运行很快的,我们阻塞队列的容量设置为了100,如果想更清晰的看到阻塞队列的效果,我们可以对消费者进行一定的限制:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;public class Demo1 {public static void main(String[] args) {//阻塞队列BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(100);//生产者Thread t1 = new Thread(()->{int n = 0;while (true){System.out.println("生产了:" + n);try {queue.put(n);} catch (InterruptedException e) {throw new RuntimeException(e);}n++;}});//消费者Thread t2 = new Thread(()->{while ( true){try {int n = queue.take();System.out.println("消费了:" + n);Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});t1.start();t2.start();}
}

由于消费者被限制了消费速度,所以当阻塞队列满了之后,生产者的生产速度也受到了影响,会形成当消费者消费之后,阻塞队列有了空间,生产者才可以继续生产。

二.阻塞队列

我们自己创建一个阻塞队列,其中阻塞队列中实现了 put() 和 take() 方法,阻塞队列的原理就像是一个环形数组,注意 head 和 tail >= 数组的长度的时候,进行一下处理就可以。

class MyBlonkingQueue{private int[] data;private int head = 0;private int tail = 0;private int size = 0;private Object locker = new Object();public MyBlonkingQueue(int capacity){data = new int[capacity];}//放入元素public void put(int elem) throws InterruptedException {synchronized(locker){if (size == data.length){locker.wait();}data[tail] = elem;locker.notify();size++;tail++;if (tail >= data.length){tail = 0;}}}//取出元素public int take() throws InterruptedException {synchronized(locker){if (size == 0){locker.wait();}int ret = data[head];size--;head++;locker.notify();if (head >= data.length){head = 0;}return ret;}}
}

运行之后发现写的阻塞数组没有问题:

public class Demo2 {public static void main(String[] args) {MyBlonkingQueue queue = new MyBlonkingQueue(10);Thread t1 = new Thread(()->{while (true){for (int i = 0; i < 10000; i++) {try {queue.put(i);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("生产了:"+i);}}});Thread t2 = new Thread(()->{while (true){int ret = 0;try {ret = queue.take();Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("消费了:"+ret);}});t1.start();t2.start();}
}

作用:

阻塞队列可以解耦合,可以使流量较为稳定,不至于因为突然的高峰期而导致服务器崩溃。削峰补谷。

三.ThreadPoolExecutor

ThreadPoolExecutor 是Java中的线程池实现类,共七个参数:

其中 corePoolSize 指的是核心线程数的数量。

maximumPoolSize 指的是最大线程数,可以根据需要在核心线程数的基础上自动扩容和缩容。

keepAliveTime 指的是非核心线程的最大存活时间。

TimeUnit unit 指的是时间单位。

workQueue 指的是要用的队列。

threadFactory 和 handler 分别是线程工厂和拒绝策略。

工厂模式:

我们在笛卡尔坐标系想要表示一个点的坐标有很多种方法:首先是 x y的表示。其次是角度加线长的办法,通过sin 和cos 来求,但是在代码中:

由于重载的要求参数要有所不同,所以上述代码是无法同时存在的,这时候就可以用工厂模式解决上述问题。如果构造对象不依赖于构造方法,那么上述问题自然就不存在了。

public class Demo3 {}
class point {public point(){}void set(){}
}
class PointFactory{public static point PointFactoryXY(int x,int y){point p = new point();p.set();return p;}public static point PointFactory(int cos,int length){point p = new point();p.set();return p;}
}

以上就是工厂模式的大致框架,通过 set 方法来把我们需要的数据设置进去,以此来达到不同房的目的。

Java 标准库中提供了ThreadFactory来于创建新线程的工厂接口。

拒绝策略:

常见的拒绝策略类型有四种:

第一种:当阻塞队列满了之后再塞入任务,会抛异常

第二种:当阻塞队列满了之后,再提交任务,会让提交当前任务的线程去执行当前任务

第三种:当阻塞队列满了之后,会移除最老的任务,让新任务加入队列。

第四种:当阻塞队列满了之后,会移除最新的任务,让新任务加入队列。

线程池的简单创建:

通过创建简单的线程池来实现生产者消费者模型:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;public class Demo5 {//创建简易的线程池static class MyThreadPool {//创建一个阻塞队列private BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();public MyThreadPool(int n) {for (int i = 0; i < 5; i++) {Thread t1 = new Thread(() -> {while (true) {try {Runnable task = queue.take();//在当前线程中执行该任务task.run();} catch (InterruptedException e) {throw new RuntimeException(e);}}},"Thread" + i);t1.start();}}public void submit(Runnable task) throws InterruptedException {queue.put(task);}}//往线程池中添加任务public static void main(String[] args) throws InterruptedException {MyThreadPool pool = new MyThreadPool(5);for (int i = 0; i < 5000; i++) {int id = i;pool.submit(()->{Thread cur = Thread.currentThread();System.out.println(cur.getName() +" " + id);});}Thread.sleep(1000);}
}

http://www.dtcms.com/a/438728.html

相关文章:

  • 浅谈内存DDR——DDR4的RASR/Bank Group等技术
  • 网站上传模板后xml天气预报网站怎么做
  • 人工智能:从技术本质到未来图景,一场正在重塑世界的变革
  • 成都私人网站制作做读书网站的前景
  • linux学习笔记(11)fork详解
  • Streamlit:CSS——从基础到实战美化应用
  • ORB_SLAM2原理及代码解析:Tracking::MonocularInitialization() 函数
  • JVM的类加载机制
  • 6. Pandas 数据排序与排名
  • lanqiao1110 小王子单链表——单链表
  • 张店网站建设价免费的编程自学软件
  • 农机网站建设目标php网站mysql数据库导入工具
  • 浙江网站建设平台app开发费用计入什么科目
  • 2025年渗透测试面试题总结-100(题目+回答)
  • 做网站赚钱容易吗推广赚钱平台有哪些
  • AutoOps:简单的 Elasticsearch 集群监控与管理现已支持本地部署
  • Async++ 源码分析3---cancel.h
  • Async++ 源码分析4---continuation_vector.h
  • 一个做搞笑类视频的网站取名网站建设平台协议书
  • 机器学习、数据科学、深度学习、神经网络的区别与联系
  • 上海嘉定网站设计商城首页网站
  • 显示系统(二):显示适配器(显卡)背后的历史
  • 嘉兴网站制作案例无代码制作网页
  • 网站页面seo做网站的语
  • 建设银行注册网站的用户名怎么写建设一个货架网站
  • 排序(Sort)
  • [Web网页] Web 基础
  • 做商铺的网站有那些怎么检查网站的死链
  • 网站做qq发送链接广东省建设监理协会网站 - 首页
  • 操作系统应用开发(十八)RustDesk-API服务器数据库——东方仙盟金丹期