java多线程设计模式demo
Master-worker模式
Master-worker模式主要由两个角色组成,master主要负责任务的分发,worker主要是任务执行
demo
client
package com.example.demo.patterns.masterworker;
import com.alibaba.fastjson.JSON;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.*;
/**
* 主线程测试类
*/
public class Main {
public static void main(String[] args) {
int availableProcessors = Runtime.getRuntime().availableProcessors();
System.out.println("核心线程数:"+ availableProcessors);
int size = 20;
//用来监听任务完成等待
CountDownLatch countDownLatch = new CountDownLatch(size);
MyWorker myWorker = new MyWorker();
myWorker.setCountDownLatch(countDownLatch);
//线程池
ExecutorService executorService = Executors.newFixedThreadPool(availableProcessors);
// 使用worker子类实现具体的业务,更加灵活
Master master = new Master(myWorker, availableProcessors,countDownLatch,executorService);
//提交10个任务
for (int i = 1; i <= size; i++) {
Task t = new Task();
t.setId(i);
master.submit(t);
}
//执行所有的worker
master.execute();
long start = System.currentTimeMillis();
//全部的worker执行结束的时候去计算最后的结果
if(master.isCompleted()){
//获取结果对象
ConcurrentHashMap<String, Object> resultMap = master.getResultMap();
for (Map.Entry<String, Object> stringObjectEntry : resultMap.entrySet()) {
System.out.println(JSON.toJSONString(stringObjectEntry.getValue()));
}
}
long end = System.currentTimeMillis();
System.out.println(String.format("执行时间:%d",end-start));
executorService.shutdown();
}
}
master
package com.example.demo.patterns.masterworker;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;
/**
* Master
*/
public class Master<T> {
//1、worker任务队列
private ConcurrentLinkedQueue<T> workQueue = new ConcurrentLinkedQueue<T>();
//2:使用hashmap去承载所有的worker对象 key:xxx value:worker任务线程
private HashMap<String,Thread> workers = new HashMap<>();
//3:用于存放子任务结果集
private ConcurrentHashMap<String,T> resultMap = new ConcurrentHashMap<String, T>();
private CountDownLatch countDownLatch;
private ExecutorService executorService;
/**
*
* @param worker worker对象
* @param workerCount 需要worker执行的线程数
*/
public Master(Worker worker, int workerCount, CountDownLatch countDownLatch, ExecutorService executorService){
//主要用于对worker对象引入工作队列与结果队列
worker.setWorkerQueue(this.workQueue);
worker.setResultMap(this.resultMap);
this.countDownLatch = countDownLatch;
this.executorService = executorService;
for (int i = 0; i < workerCount; i++) {
//存入线程
workers.put(String.format("worker[%d]",i), new Thread(worker));
}
}
//存入任务队列,主要用worker去任务队列取值,然后执行,多任务多线程在
//队列取值执行
public void submit(T t){
workQueue.add(t);
}
//执行方法
public void execute(){
//异步执行worker线程
for (Map.Entry<String,Thread> entry: workers.entrySet()) {
executorService.submit(entry.getValue());
}
}
/**
* 判断所有的worker是否执行完毕
*/
public boolean isCompleted(){
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
return true;
}
public ConcurrentHashMap<String, T> getResultMap() {
return resultMap;
}
}
worker
package com.example.demo.patterns.masterworker;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
/**
* 抽象类,模板方法
*/
public abstract class Worker<T> implements Runnable {
private ConcurrentLinkedQueue<T> workQueue;
private ConcurrentHashMap<String, T> resultMap;
protected CountDownLatch countDownLatch;
public void setWorkerQueue(ConcurrentLinkedQueue<T> workQueue) {
this.workQueue = workQueue;
}
public void setResultMap(ConcurrentHashMap<String, T> resultMap) {
this.resultMap = resultMap;
}
@Override
public void run() {
//处理一个个任务
while(true){
//从队列中取出一个元素
T input = this.workQueue.poll();
//队列为空说明任务都已经执行完成
if(null == input) break;
//真正的去做业务处理
T outPut = handle(input);
//存放任务的结果
this.resultMap.put(UUID.randomUUID().toString(), outPut);
}
}
//单独抽出来 给子类重写,更加灵活
public abstract T handle(T input);
public void setCountDownLatch(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
}
模板方法的实现类
package com.example.demo.patterns.masterworker;
import java.util.concurrent.TimeUnit;
public class MyWorker extends Worker<Task> {
@Override
public Task handle(Task task) {
if(task == null){
return null;
}
try {
//莫你业务逻辑,对age进行计算赋值
TimeUnit.SECONDS.sleep(2);
task.setAge(task.getId()*10);
super.countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
return task;
}
}
任务类
package com.example.demo.patterns.masterworker;
/**
* 任务
*/
public class Task
{
private int id;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
运行结果:
可以看到12个任务,每个任务2秒,一共就执行2秒钟,说明了都是并行执行,并且一次就可以全部执行完了。
核心线程数:12
{
"age":190,"id":19}
{
"age":10,"id":1}
{
"age":140,"id":14}
{
"age":90,"id":9}
{
"age":170,"id":17}
{
"age":180,"id":18}
{
"age":30,"id":3}
{
"age":40,"id":4}
{
"age":120,"id":12}
{
"age":150,"id":15}
{
"age":50,"id":5}
{
"age":80,"id":8}
{
"age":100,"id":10}
{
"age":200,"id":20}
{
"age":60,"id":6}
{
"age":110,"id":11}
{
"age":70,"id":7}
{
"age":20,"id":2}
{
"age":160,"id":16}
{
"age":130,"id":13}
执行时间:4652
生产者消费者模式
client
package com.example.demo.patterns.queue;
import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
public class Main {
public static void main(String[] args) throws IOException {
int availableProcessors = Runtime.getRuntime().availableProcessors();
//生产者往队列放数据,队列为阻塞队列,队列大小
int size = 10;
BlockingQueue<Data> queue=new LinkedBlockingQueue<>(size);
//3生产者 3个消费者
Product product=new Product(queue);
Product product1=new Product(queue);
Product product2=new Product(queue);
Consumer consumer=new Consumer(queue);
Consumer consumer1=new Consumer(queue);
Consumer consumer2=new Consumer(queue);
ExecutorService executorService= Executors.newFixedThreadPool(availableProcessors);
executorService.execute(product);
executorService.execute(product1);
executorService.execute(product2);
executorService.execute(consumer);
executorService.execute(consumer1);
executorService.execute(consumer2);
// System.in.read();
try {
Thread.sleep(2000);
product.stop();
product1.stop();
product2.stop();
executorService.shutdown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
生产者
package com.example.demo.patterns.queue;
import com.alibaba.fastjson.JSON;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 生产者
*/
public class Product implements Runnable{
private BlockingQueue<Data> queue;
private volatile boolean running=true;
public Product(BlockingQueue<Data> queue) {
this.queue=queue;
}
@Override
public void run() {
while(running) {
try {
Thread.sleep(500);
Data data=new Data();
data.setName(UUID.randomUUID().toString());
System.out.println(String.format("生产者生产数据[%s]", JSON.toJSONString(data)));
queue.offer(data);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void stop() {
this.running=false;
}
}
消费者
扫描二维码关注公众号,回复:
12575386 查看本文章
package com.example.demo.patterns.queue;
import com.alibaba.fastjson.JSON;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
/**
* 消费者
*/
public class Consumer implements Runnable{
private volatile boolean running=true;
private BlockingQueue<Data> queue;
public Consumer(BlockingQueue<Data> queue) {
this.queue=queue;
}
@Override
public void run() {
while (running) {
try {
Thread.sleep(2000);
//没有数据会阻塞
Data data=this.queue.take();
System.out.println(String.format("消费者消费数据[%s]", JSON.toJSONString(data)));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
数据
package com.example.demo.patterns.queue;
public class Data {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
结果
生产者生产数据[{
"name":"24d364f8-0c1c-45e1-bebc-a3083562c6e9"}]
生产者生产数据[{
"name":"0a27207f-9776-491d-99d2-85f66342b44c"}]
生产者生产数据[{
"name":"fc17c1a9-1ca6-4b3b-afc6-ccee30dae4e9"}]
生产者生产数据[{
"name":"603882f2-9096-41e1-8b84-7af7b1b1ad68"}]
生产者生产数据[{
"name":"ccf8bc1b-90bb-45ae-a27f-b39f4fe3f047"}]
生产者生产数据[{
"name":"8dabb0c6-c4ee-469d-b14d-9928e3ef6580"}]
消费者消费数据[{
"name":"24d364f8-0c1c-45e1-bebc-a3083562c6e9"}]
消费者消费数据[{
"name":"fc17c1a9-1ca6-4b3b-afc6-ccee30dae4e9"}]
消费者消费数据[{
"name":"0a27207f-9776-491d-99d2-85f66342b44c"}]
生产者生产数据[{
"name":"f0f3351a-218b-40c0-9720-119c2a3c6bcd"}]
生产者生产数据[{
"name":"02cb0cb8-5669-403c-b884-c7a882b512e4"}]
生产者生产数据[{
"name":"d7012e1b-d6b0-4d1f-a519-087a83518caa"}]
消费者消费数据[{
"name":"603882f2-9096-41e1-8b84-7af7b1b1ad68"}]
消费者消费数据[{
"name":"ccf8bc1b-90bb-45ae-a27f-b39f4fe3f047"}]
消费者消费数据[{
"name":"8dabb0c6-c4ee-469d-b14d-9928e3ef6580"}]
消费者消费数据[{
"name":"d7012e1b-d6b0-4d1f-a519-087a83518caa"}]
消费者消费数据[{
"name":"f0f3351a-218b-40c0-9720-119c2a3c6bcd"}]
消费者消费数据[{
"name":"02cb0cb8-5669-403c-b884-c7a882b512e4"}]
furture模式
jdk1.8对furter进行优化,用completeablefurture,我们直接将completeablefurture例子
异步带返回值的逻辑,串行操作
package com.example.demo.completefuture;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CompletableFutureDemo {
public static void main(String[] args) {
// CompletableFuture.runAsync()
// CompletableFuture.supplyAsync()
ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
//异步按照顺序执行,一个异步任务执行完成后接着执行
//参数Supplier 接受生产者 只有返回值,代表数据的生产
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "张三";
}, executorService);
//参数为function,一个参数 一个返回值,代码函数式接口,处理逻辑然后返回
CompletableFuture<String> completableFuture1 = completableFuture.thenApply(result -> {
try {
Thread.sleep(2000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
return result + "去";
});
CompletableFuture<String> completableFuture2 = completableFuture1.thenApply(result -> {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
return result + "吃火锅!";
});
//参数为Consumer,代表消费者对象
completableFuture2.thenAccept(System.out::println);
//抛异常执行的逻辑
completableFuture2.exceptionally(e->{
e.printStackTrace();
return null;
});
//可以执行自己的业务逻辑
System.out.println("主线程任务执行");
//等待线程执行完成
executorService.shutdown();
}
}
主线程任务执行
张三去吃火锅!
异步不带返回值逻辑
public class CompletableFutureDemo2 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
try {
Thread.sleep(3000L);
System.out.println("处理业务逻辑");
} catch (InterruptedException e) {
e.printStackTrace();
}
},executorService);
Consumer consumer = a-> System.out.println("任务处理完成");
executorService.shutdown();
completableFuture.thenAccept(consumer);
}
}
处理业务逻辑
任务处理完成
还可以并行执行
package com.example.demo.completefuture;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CompletableFutureDemo3 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
long start = System.currentTimeMillis();
CompletableFuture<String> zs = CompletableFuture.supplyAsync(() ->{
try {
Thread.sleep(1000L);
System.out.println("处理第一个逻辑");
} catch (InterruptedException e) {
e.printStackTrace();
}
return "处理第一个逻辑";
},executorService);
CompletableFuture<String> ls = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000L);
System.out.println("处理第二个逻辑");
} catch (InterruptedException e) {
e.printStackTrace();
}
return "处理第二个逻辑";
},executorService);
//代表两个任务任意一种,可以跟很多个任务,不只是两个,参数是一个数组
// CompletableFuture.anyOf()
//代表两者的所有
CompletableFuture<Void> completableFuture = CompletableFuture.allOf(zs, ls);
completableFuture.join();
System.out.println("主函数执行时间:"+(System.currentTimeMillis()-start));
System.out.println("第一个任务值:"+zs.get());
System.out.println("第二个任务值:"+ls.get());
executorService.shutdown();
}
}
处理第一个逻辑
处理第二个逻辑
主函数执行时间:3046
第一个任务值:处理第一个逻辑
第二个任务值:处理第二个逻辑