Java线程设计模式(五)
多线程的设计模式:Future模式、Master-Worker模式,生产消费者模式
public interface Data { String getRequest();
}
public class FutureClient {
public Data request(final String queryStr){
//1 我想要一个代理对象(Data接口的实现类)先返回给发送请求的客户端,告诉他请求已经接收到,可以做其他的事情
final FutureData futureData = new FutureData();
//2 启动一个新的线程,去加载真实的数据,传递给这个代理对象
new Thread(new Runnable() {
@Override
public void run() {
//3 这个新的线程可以去慢慢的加载真实对象,然后传递给代理对象
RealData realData = new RealData(queryStr);
futureData.setRealData(realData);
}
}).start(); return futureData;
}
}
public class FutureData implements Data{ private RealData realData ; private boolean isReady = false; public synchronized void setRealData(RealData realData) {
//如果已经装载完毕了,就直接返回
if(isReady){
return;
}
//如果没装载,进行装载真实对象
this.realData = realData;
isReady = true;
//进行通知
notify();
} @Override
public synchronized String getRequest() {
//如果没装载好 程序就一直处于阻塞状态
while(!isReady){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//装载好直接获取数据即可
return this.realData.getRequest();
}
}
public class RealData implements Data{ private String result ; public RealData (String queryStr){
System.out.println("根据" + queryStr + "进行查询,这是一个很耗时的操作..");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("操作完毕,获取结果");
result = "查询结果";
} @Override
public String getRequest() {
return result;
}
}
public class Main {
public static void main(String[] args) throws InterruptedException { FutureClient fc = new FutureClient();
Data data = fc.request("请求参数");
System.out.println("请求发送成功!");
System.out.println("做其他的事情..."); String result = data.getRequest();
System.out.println(result);
}
}
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue; public class Master {
//1 有一个盛放任务的容器
private ConcurrentLinkedQueue<Task> workQueue=new ConcurrentLinkedQueue<Task>(); //2 需要有一个盛放worker的集合
private HashMap<String,Thread> workers =new HashMap<String, Thread>(); //3 需要有一个盛放每一个worker执行任务的结果集合
private ConcurrentHashMap<String,Object> resultMap=new ConcurrentHashMap<String, Object>(); //4 构造方法
public Master(Worker worker,int workerCount){
worker.setWorkQueue(this.workQueue);
worker.setResultMap(this.resultMap);
for(int i = 0; i < workerCount; i ++){
this.workers.put(Integer.toString(i), new Thread(worker));
}
}
//5 需要一个提交任务的方法
public void submit(Task task) {
this.workQueue.add(task);
}
//6 需要有一个执行的方法,启动所有的worker方法去执行任务
public void execute(){
for(Map.Entry<String,Thread> me: workers.entrySet()){
me.getValue().start();
}
}
//7 判断是否运行结束的方法
public boolean isComplete() {
for(Map.Entry<String, Thread> me : workers.entrySet()){
if(me.getValue().getState() != Thread.State.TERMINATED){
return false;
}
}
return true;
} //8 计算结果方法
public int getResult() {
int priceResult = 0;
for(Map.Entry<String, Object> me : resultMap.entrySet()){
priceResult += (Integer)me.getValue();
}
return priceResult;
}
}
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue; public class Worker implements Runnable{
private ConcurrentLinkedQueue<Task> workQueue;
private ConcurrentHashMap<String,Object> resultMap;
public void setWorkQueue(ConcurrentLinkedQueue<Task> workQueue) {
this.workQueue=workQueue;
}
public void setResultMap(ConcurrentHashMap<String,Object> resultMap){
this.resultMap=resultMap;
}
@Override
public void run(){
while (true){
Task input=this.workQueue.poll();
if(input==null) break;
Object output=handle(input);
this.resultMap.put(Integer.toString(input.getId()),output);
}
}
private Object handle(Task input){
Object output=null;
try {
//处理任务的耗时。。 比如说进行操作数据库。。。
Thread.sleep(500);
output = input.getPrice();
} catch (InterruptedException e) {
e.printStackTrace();
}
return output;
}
}
public class Task {
private int id;
private int price ;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
import java.util.Random; public class Main {
public static void main(String[] args) {
Master master = new Master(new Worker(), 20); Random r = new Random();
for (int i = 1; i <= 100; i++) {
Task t = new Task();
t.setId(i);
t.setPrice(r.nextInt(1000));
master.submit(t);
}
master.execute();
long start = System.currentTimeMillis(); while (true) {
if (master.isComplete()) {
long end = System.currentTimeMillis() - start;
int priceResult = master.getResult();
System.out.println("最终结果:" + priceResult + ", 执行时间:" + end);
break;
}
} }
}
生产者-消费者
public final class Data {
private String id;
private String name; public Data(String id, String name){
this.id = id;
this.name = name;
} public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @Override
public String toString(){
return "{id: " + id + ", name: " + name + "}";
}
}
import java.util.Random;
import java.util.concurrent.BlockingQueue; public class Consumer implements Runnable{
private BlockingQueue<Data> queue;
public Consumer(BlockingQueue queue){
this.queue=queue;
}
//随机对象
private static Random r = new Random();
@Override
public void run() {
while(true){
try {
//获取数据
Data data = this.queue.take();
//进行数据处理。休眠0 - 1000毫秒模拟耗时
Thread.sleep(r.nextInt(1000));
System.out.println("当前消费线程:" + Thread.currentThread().getName() + ", 消费成功,消费数据为id: " + data.getId());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Provider implements Runnable{ //共享缓存区
private BlockingQueue<Data> queue;
//多线程间是否启动变量,有强制从主内存中刷新的功能。即时返回线程的状态
private volatile boolean isRunning = true;
//id生成器
private static AtomicInteger count = new AtomicInteger();
//随机对象
private static Random r = new Random(); public Provider(BlockingQueue queue){
this.queue = queue;
} @Override
public void run() {
while(isRunning){
try {
//随机休眠0 - 1000 毫秒 表示获取数据(产生数据的耗时)
Thread.sleep(r.nextInt(1000));
//获取的数据进行累计...
int id = count.incrementAndGet();
//比如通过一个getData方法获取了
Data data = new Data(Integer.toString(id), "数据" + id);
System.out.println("当前线程:" + Thread.currentThread().getName() + ", 获取了数据,id为:" + id + ", 进行装载到公共缓冲区中...");
if(!this.queue.offer(data, 2, TimeUnit.SECONDS)){
System.out.println("提交缓冲区数据失败....");
//do something... 比如重新提交
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} public void stop(){
this.isRunning = false;
}
}
public class Main { public static void main(String[] args) throws Exception {
//内存缓冲区
BlockingQueue<Data> queue = new LinkedBlockingQueue<Data>(10);
//生产者
Provider p1 = new Provider(queue); Provider p2 = new Provider(queue);
Provider p3 = new Provider(queue);
//消费者
Consumer c1 = new Consumer(queue);
Consumer c2 = new Consumer(queue);
Consumer c3 = new Consumer(queue);
//创建线程池运行,这是一个缓存的线程池,可以创建无穷大的线程,没有任务的时候不创建线程。空闲线程存活时间为60s(默认值) ExecutorService cachePool = Executors.newCachedThreadPool();
cachePool.execute(p1);
cachePool.execute(p2);
cachePool.execute(p3);
cachePool.execute(c1);
cachePool.execute(c2);
cachePool.execute(c3); try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
p1.stop();
p2.stop();
p3.stop();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// cachePool.shutdown();
// cachePool.shutdownNow(); }
}
Java线程设计模式(五)的更多相关文章
- java 线程(五)线程安全 Lock接口
package cn.sasa.demo3; import java.util.concurrent.ExecutionException; public class ThreadDemo { pub ...
- java线程的五种状态
五种状态 开始状态(new) 就绪状态(runnable) 运行状态(running) 阻塞状态(blocked) 结束状态(dead) 状态变化 1.线程刚创建时,是new状态 2.线程调用了sta ...
- java常用设计模式五:建造者模式
1.定义 是一种对象构建的设计模式,它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象. 产品类:一般是一个较为复杂的对象,也就是说创建对象的 ...
- Java线程的五种状态详解
状态转换图 1.new状态:通过new关键字创建了Thread或其子类的对象 2.Runnable状态:即就绪状态.可从三种状态到达,new状态的Thread对象调用start()方法,Running ...
- 细说进程五种状态的生老病死——双胞胎兄弟Java线程
java线程的五种状态其实要真正高清,只需要明白计算机操作系统中进程的知识,原理都是相同的. 系统根据PCB结构中的状态值控制进程. 单CPU系统中,任一时刻处于执行状态的进程只有一个. 进程的五种状 ...
- java常用设计模式总览
一.java的设计模式大体上分为三大类: 创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式. 结构型模式(7种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组 ...
- java线程池与五种常用线程池策略使用与解析
背景:面试中会要求对5中线程池作分析.所以要熟知线程池的运行细节,如CachedThreadPool会引发oom吗? java线程池与五种常用线程池策略使用与解析 可选择的阻塞队列BlockingQu ...
- Java线程创建形式 Thread构造详解 多线程中篇(五)
Thread作为线程的抽象,Thread的实例用于描述线程,对线程的操纵,就是对Thread实例对象的管理与控制. 创建一个线程这个问题,也就转换为如何构造一个正确的Thread对象. 构造方法列表 ...
- Java多线程(五)线程的生命周期
点我跳过黑哥的卑鄙广告行为,进入正文. Java多线程系列更新中~ 正式篇: Java多线程(一) 什么是线程 Java多线程(二)关于多线程的CPU密集型和IO密集型这件事 Java多线程(三)如何 ...
随机推荐
- #C++初学记录(奶酪#并查集)
原题目:牛客网 题目描述 : 现有一块大奶酪,它的高度为 h,它的长度和宽度我们可以认为是无限大的,奶酪中间有许多半径相同的球形空洞.我们可以在这块奶酪中建立空间坐标系, 在坐标系中,奶酪的下表面为 ...
- __gcd-最大公约数
__gcd-最大公约数 最大公约数(greatest common divisor,简写为gcd:或highest common factor,简写为hcf) __gcd(x,y)是algorithm ...
- 虚拟机VirtualBox 共享挂载问题:mount: /mnt/xxx: wrong fs type, bad option, bad superblock on xxx
设置好共享文件夹之后,在/mnt下面建立了一个wwwroot文件夹,然后去欢天喜地的去挂载, mount -t vboxsf www /mnt/wwwroot 结果系统提示: mount: /mnt/ ...
- Tomcat 配置虚拟目录以及虚拟主机
目录 虚拟目录 虚拟主机 虚拟目录 虚拟目录的功能 一般情况下,我们的打包后的项目都是放到tomcat/webapps目录下的,然后通过localhost:8080/project_name这个链接进 ...
- Navicat 破解版链接
本文为转载内容 百度网盘地址: https://pan.baidu.com/s/1nvIIOad 压缩包中有注册码和使用方法
- Mysql查询的执行顺序
顺序: FROM JOIN ON WHERE GROUP BY (从此处开始可以使用select中指定的别名) AVG.SUM.MAX HAVING SELECT DISTINCT ORDER BY ...
- Kafka生产者性能优化之吞吐量VS延迟
When we are talking about performance of Kafka Producer, we are really talking about two different t ...
- rConfig v3.9.2 授权认证与未授权RCE (CVE-2019-16663) 、(CVE-2019-16662)
rConfig v3.9.2 authenticated and unauthenticated RCE (CVE-2019-16663) and (CVE-2019-16662) 原文:https: ...
- 【电商日志项目之五】数据分析-MR方式
环境 hadoop-2.6.5 hbase-0.98.12.1-hadoop2 新增用户指标分析(1)用户分析模块 (2)浏览器分析模块 根据分析效果图,找出分析的维度:用户分析是指某个时间段内的数量 ...
- Kubernetes 集群日志管理 Elasticsearch + fluentd(二十)
目录 一.安装部署 Kubernetes 开发了一个 Elasticsearch 附加组件来实现集群的日志管理.这是一个 Elasticsearch.Fluentd 和 Kibana 的组合.Elas ...