• java架构《并发线程中级篇》


    java多线程的三大设计模式

        本章主要记录java常见的三大设计模式,Future、Master-Worker和生产者-消费者模式。

    一、Future模式

        使用场景:数据可以不及时返回,到下一次实际要使用结果的之前,后台自动查询并返回。类似与Ajax异步加载。

        原理:客户端发起请求,结果需要返回Data对象,当服务器收到请求以后,FutureData包装类实现Data接口,不查询数据库,直接返回结果。(核心)。然后后台自己开一个线程去查询数据库,RealData真

           实数据类,也实现Data接口,并返回数据。当实际使用时。获取到返回的真实数据。

            

          代码分析:

          

     1 //  FutureClient 客户端类:
     2 
     3       public class FutureClient {
     4 
     5       public Data request(final String queryStr){
     6           //1 我想要一个代理对象(Data接口的实现类)先返回给发送请求的客户端,告诉他请求已经接收到,可以做其他的事情
     7           final FutureData futureData = new FutureData();
     8           //2 启动一个新的线程,去加载真实的数据,传递给这个代理对象
     9           new Thread(new Runnable() {
    10           @Override
    11           public void run() {
    12               //3 这个新的线程可以去慢慢的加载真实对象,然后传递给代理对象
    13               RealData realData = new RealData(queryStr);
    14               futureData.setRealData(realData);
    15               }
    16           }).start();
    17           return futureData;
    18           }
    19 
    20  

        

     1  // Data类:
     2 
     3       
     4 
     5         public interface Data {
     6 
     7           String getRequest();
     8 
     9         }
    10 
    11   

        

     1  // FutureData类:   
     2 
     3         public class FutureData implements Data{
     4 
     5         private RealData realData ;
     6 
     7           private boolean isReady = false;
     8 
     9           public synchronized void setRealData(RealData realData) {
    10           //如果已经装载完毕了,就直接返回
    11           if(isReady){
    12                 return;
    13                  }
    14               //如果没装载,进行装载真实对象
    15                  this.realData = realData;
    16                  isReady = true;
    17               //进行通知
    18                 notify();
    19              }
    20 
    21           @Override
    22           public synchronized String getRequest() {
    23           //如果没装载好 程序就一直处于阻塞状态
    24             while(!isReady){
    25             try {
    26               wait();
    27               } catch (InterruptedException e) {
    28                 e.printStackTrace();
    29               }
    30               }
    31               //装载好直接获取数据即可
    32               return this.realData.getRequest();
    33               }
    34 
    35  
    36 
    37              }
    38 
    39  

         

     1 // RealData类:   
     2 
     3         public class RealData implements Data{
     4 
     5         private String result ;
     6 
     7         public RealData (String queryStr){
     8             System.out.println("根据" + queryStr + "进行查询,这是一个很耗时的操作..");
     9             try {
    10               Thread.sleep(5000);
    11               } catch (InterruptedException e) {
    12                 e.printStackTrace();
    13               }
    14                 System.out.println("操作完毕,获取结果");
    15                 result = "查询结果";
    16               }
    17 
    18            @Override
    19               public String getRequest() {
    20               return result;
    21              }
    22 
    23             }
    24 
    25  

         

     1 // Main测试类:            
     2 
     3         public class Main {
     4 
     5             public static void main(String[] args) throws InterruptedException {
     6 
     7             FutureClient fc = new FutureClient();
     8             Data data = fc.request("请求参数");
     9             System.out.println("请求发送成功!");
    10             System.out.println("做其他的事情...");
    11             String result = data.getRequest();
    12             System.out.println(result);
    13           }
    14         }

     

    二:Master-Worker模式(并行计算模式)      

        使用场景:互不影响的多任务时。返回结果需要共同返回。其好处是讲一个大任务分解成若干个小任务。并行执行,提高系统的吞吐量。

        原理:核心思想是系统由两类进程协作工作;Master进程和Worker进程。Master进程负责接收和分配工作,Worker进程主要负责处理子任务。当各
           个Worker进程处理完后。会将结果返回给Master,由Master做归纳和总结,并返回。

          

          

          

        

        

        

        代码分析:

          

     1 //Worker类:
     2 
     3       public class Worker implements Runnable {
     4 
     5         private ConcurrentLinkedQueue<Task> workQueue;
     6         private ConcurrentHashMap<String, Object> resultMap;
     7 
     8         public void setWorkQueue(ConcurrentLinkedQueue<Task> workQueue) {
     9           this.workQueue = workQueue;
    10         }
    11 
    12         public void setResultMap(ConcurrentHashMap<String, Object> resultMap) {
    13           this.resultMap = resultMap;
    14         }
    15 
    16         @Override
    17         public void run() {
    18           while(true){
    19             Task input = this.workQueue.poll();
    20               if(input == null) break;
    21                 Object output = handle(input);
    22                 this.resultMap.put(Integer.toString(input.getId()), output);
    23               }
    24             }
    25 
    26         private Object handle(Task input) {
    27             Object output = null;
    28               try {
    29                 //处理任务的耗时。。 比如说进行操作数据库。。。
    30                 Thread.sleep(500);
    31                 output = input.getPrice();   //模拟把Task类的价格做为结果返回
    32                 } catch (InterruptedException e) {
    33                 e.printStackTrace();
    34                 }
    35                 return output;
    36              }
    37 
    38          }
    39 
    40  

        

     1  //Master类:
     2 
     3       public class Master {
     4 
     5         //1 有一个盛放任务的容器
     6         private ConcurrentLinkedQueue<Task> workQueue = new ConcurrentLinkedQueue<Task>();
     7 
     8         //2 需要有一个盛放worker的集合
     9         private HashMap<String, Thread> workers = new HashMap<String, Thread>();
    10 
    11         //3 需要有一个盛放每一个worker执行任务的结果集合
    12         private ConcurrentHashMap<String, Object> resultMap = new ConcurrentHashMap<String, Object>();
    13 
    14         //4 构造方法
    15         public Master(Worker worker , int workerCount){
    16           worker.setWorkQueue(this.workQueue);
    17           worker.setResultMap(this.resultMap);
    18 
    19           for(int i = 0; i < workerCount; i ++){
    20               this.workers.put(Integer.toString(i), new Thread(worker));
    21             }
    22             }
    23 
    24           //5 需要一个提交任务的方法
    25        public void submit(Task task){
    26             this.workQueue.add(task);
    27             }
    28 
    29           //6 需要有一个执行的方法,启动所有的worker方法去执行任务
    30       public void execute(){
    31           for(Map.Entry<String, Thread> me : workers.entrySet()){
    32               me.getValue().start();
    33             }
    34             }
    35 
    36           //7 判断是否运行结束的方法
    37       public boolean isComplete() {
    38           for(Map.Entry<String, Thread> me : workers.entrySet()){
    39               if(me.getValue().getState() != Thread.State.TERMINATED){
    40               return false;
    41                 }
    42               }    
    43             return true;
    44           }
    45 
    46           //8 计算结果方法
    47       public int getResult() {
    48           int priceResult = 0;
    49           for(Map.Entry<String, Object> me : resultMap.entrySet()){
    50           priceResult += (Integer)me.getValue();
    51           }
    52           return priceResult;
    53           }
    54       }

        

         

     1 // Task类:
     2 
     3         
     4 
     5       public class Task {
     6 
     7         private int id;
     8         private int price ;
     9         public int getId() {
    10           return id;
    11            }
    12         public void setId(int id) {
    13           this.id = id;
    14           }
    15         public int getPrice() {
    16           return price;
    17           }
    18         public void setPrice(int price) {
    19           this.price = price;
    20         } 
    21        }
    22 
    23  

          

     1 //main测试类:
     2 
     3          public class Main {
     4 
     5           public static void main(String[] args) {
     6 
     7           int Processors= Runtime.getRuntime().availableProcessors(); //获取到当前电脑的线程数
     8           System.out.println("当前电脑是"+Processors+"核");
     9           Master master = new Master(new Worker(),Processors );
    10           //Master master = new Master(new Worker(),20 ); //开20个线程
    11           Random r = new Random();
    12           for(int i = 1; i <= 100; i++){
    13             Task t = new Task();
    14             t.setId(i);
    15             t.setPrice(r.nextInt(1000));
    16             master.submit(t);
    17             }
    18             master.execute();  //执行任务
    19             long start = System.currentTimeMillis();
    20 
    21             while(true){
    22             if(master.isComplete()){
    23             long end = System.currentTimeMillis() - start;
    24             int priceResult = master.getResult();
    25             System.out.println("最终结果:" + priceResult + ", 执行时间:" + end);
    26             break;
    27             }
    28             }
    29           }
    30         }
    31 
    32  

    三:生产者-消费者模式

        使用场景:消息中间件。

          

        代码分析:

           

     1 // main测试类:  
     2 
     3           public class Main {
     4 
     5           public static void main(String[] args) throws Exception {
     6           //内存缓冲区
     7           BlockingQueue<Data> queue = new LinkedBlockingQueue<Data>(10);
     8           //生产者
     9           Provider p1 = new Provider(queue);
    10           Provider p2 = new Provider(queue);
    11           Provider p3 = new Provider(queue);
    12           //消费者
    13           Consumer c1 = new Consumer(queue);
    14           Consumer c2 = new Consumer(queue);
    15           Consumer c3 = new Consumer(queue);
    16           //创建线程池运行,这是一个缓存的线程池,可以创建无穷大的线程,没有任务的时候不创建线程。空闲线程存活时间为60s(默认值)  
    17 
    18           ExecutorService cachePool = Executors.newCachedThreadPool();
    19 
    20           cachePool.execute(p1);
    21           cachePool.execute(p2);
    22           cachePool.execute(p3);
    23           cachePool.execute(c1);
    24           cachePool.execute(c2);
    25           cachePool.execute(c3);
    26 
    27           try {
    28             Thread.sleep(3000);
    29             } catch (InterruptedException e) {
    30               e.printStackTrace();
    31             }
    32               p1.stop();
    33               p2.stop();
    34               p3.stop();
    35           try {
    36             Thread.sleep(2000);
    37             } catch (InterruptedException e) {
    38               e.printStackTrace();
    39             }    
    40           }
    41 
    42         }
    43 
    44  

         

     1  Data类:        
     2 
     3         public final class Data {
     4 
     5         private String id;
     6         private String name;
     7 
     8         public Data(String id, String name){
     9           this.id = id;
    10           this.name = name;
    11           }
    12 
    13         public String getId() {
    14           return id;
    15           }
    16 
    17         public void setId(String id) {
    18           this.id = id;
    19           }
    20 
    21         public String getName() {
    22           return name;
    23           }
    24 
    25         public void setName(String name) {
    26           this.name = name;
    27           }
    28 
    29         @Override
    30         public String toString(){
    31           return "{id: " + id + ", name: " + name + "}";
    32           }
    33 
    34         }
    35 
    36  

         

     1  //Provider成产者类:
     2 
     3         
     4 
     5         public class Provider implements Runnable{
     6 
     7             //共享缓存区
     8           private BlockingQueue<Data> queue;
     9             //多线程间是否启动变量,有强制从主内存中刷新的功能。即时返回线程的状态
    10           private volatile boolean isRunning = true;
    11             //id生成器
    12           private static AtomicInteger count = new AtomicInteger();
    13             //随机对象
    14           private static Random r = new Random(); 
    15 
    16           public Provider(BlockingQueue queue){
    17             this.queue = queue;
    18             }
    19 
    20           @Override
    21           public void run() {
    22           while(isRunning){
    23             try {
    24               //随机休眠0 - 1000 毫秒 表示获取数据(产生数据的耗时) 
    25               Thread.sleep(r.nextInt(1000));
    26               //获取的数据进行累计...
    27               int id = count.incrementAndGet();
    28               //比如通过一个getData方法获取了
    29               Data data = new Data(Integer.toString(id), "数据" + id);
    30               System.out.println("当前线程:" + Thread.currentThread().getName() + ", 获取了数据,id为:" + id + ", 进行装载到公共缓冲区中...");
    31               if(!this.queue.offer(data, 2, TimeUnit.SECONDS)){
    32               System.out.println("提交缓冲区数据失败....");
    33               //do something... 比如重新提交
    34               }
    35             } catch (InterruptedException e) {
    36               e.printStackTrace();
    37             }
    38           }
    39           }
    40 
    41           public void stop(){
    42             this.isRunning = false;
    43           }
    44 
    45         }
    46 
    47  

        

     1  // ConSumber消费者类:
     2 
     3         
     4 
     5         public class Consumer implements Runnable{
     6 
     7           private BlockingQueue<Data> queue;
     8 
     9           public Consumer(BlockingQueue queue){
    10           this.queue = queue;
    11           }
    12 
    13           //随机对象
    14           private static Random r = new Random();
    15 
    16           @Override
    17           public void run() {
    18             while(true){
    19               try {
    20               //获取数据
    21               Data data = this.queue.take();
    22               //进行数据处理。休眠0 - 1000毫秒模拟耗时
    23               Thread.sleep(r.nextInt(1000));
    24               System.out.println("当前消费线程:" + Thread.currentThread().getName() + ", 消费成功,消费数据为id: " + data.getId());
    25               } catch (InterruptedException e) {
    26                 e.printStackTrace();
    27               }
    28             }
    29             }
    30          }
    31 
    32  
  • 相关阅读:
    正则表达式
    Requests库基本使用(转载)
    prometheus + grafana + pushgateway 搭建监控可视化系统
    Docker的系统资源限制(转载)
    DAY8 文件操作
    DAY7 集合,深浅copy
    DAY6 Python之代码块,小数据池的详解
    DAY5 Python基础类型之字典
    DAY4 Python数据类型之列表
    DAY3 python基础之数据类型总览
  • 原文地址:https://www.cnblogs.com/coes/p/6856537.html
Copyright © 2020-2023  润新知