• Java 进阶7 并发优化 1 并行程序的设计模式


    Java 进阶7 并发优化 1 并行程序的设计模式 20131114
    本章重点介绍的是基于 Java并行程序开发以及优化的方法,对于多核的 CPU,传统的串行程序已经很好的发回了 CPU性能,此时如果想进一步提高程序的性能,就应该使用多线程并行的方式挖掘 CPU的潜能。本章知识点:
              常用的多线程设计模式,比如 Future模式,Master-Worker 模式,Guarded Suspeionsion模式、不变模式、生产者消费者模式等等。
             JDK 内置的多线程框架和各种线程池技术;
             JDK 内置的并发数据结构;
             JDK 并发控制方式,比如内部锁,重入锁,读写锁, ThreadLocal变量,信号量等等
              有关锁的一些优化方法;
              使用无锁的方式提高程序性能;
              使用轻量级的协称获得更高的并行度。
    1. 并行程序的设计模式
              并行程序的设计模式也是并行程序优化的一部分,他是对一些常用的多线程结构的总结和抽象。和串行程序相比的话,并行程序的结构更为复杂,因此合理的好似用并行模式在多线程的开发中是有助于程序的优化。经常使用的是 Future模式, Master-Worker模式, Guarded Suspeionsion模式,不变模式,生产者 -消费者模式。
    1.1Future 模式
              有点类似的商品的订单,网上下订单,之后交给商家来进行处理,我们只是等待结果,在这个等待的过程中,我们可以处理其他的事物。类比到程序中,我们在程序中提交了一个请求的话,可能是互联网请求获得其他 HTTP Web等等,传统的单线程环境下面,调用的函数是同步的,也就是说必须等到结果返回之后,才能够进行其他的处理。在 Future模式中,采用的是异步的方式,返回主调函数中,如果可以继续处理其他事物的话,就会继续处理其他的事物。这样的话,就不会出现所谓的等待时间,提高系统的响应速度。
             Future 模式的主要参与者:
             Main          系统启动,调用 Client发出请求;
             Client         返回Data对象,立即返回 FutureData,并且开启ClientThread 线程装配 RealData
             Data                    返回数据的接口;
             FutureData      Future 数据,构造很快,但是是一个虚拟的数据,需要装配 Real数据;
             RealData  真实数据,其构造过程比较耗时;
    TestMain.java
    public class TestMain {
        /*
         * main 函数的实现 主要负责是调用Client吗,发起请求,使用返回的数据
         */
        public static void main(String[] args)  {
             // TODO Auto-generated method stub
            Client client  = new Client();
            Data data = client.request( "name");
            System. out.println("request finished" );
            
             try {
                Thread. sleep(2000);//期间可以处理其他的事务
            } catch (InterruptedException e) {
                 // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            System. out.println("request data:" + data.getResult());
        }
    }
    Client.java
    public class Client {
        public Data request( final String queryStr){
             final FutureData future = new FutureData();
             new Thread(){
                 public void run(){
                    RealData realData = new RealData(queryStr);
                    future.setRealData(realData);
                }
            }.start();
            
             return future;
        }
    }
    Data.java
    public interface Data {
        public String getResult();
    }
    FutureData.java
    public class FutureData implements Data{
        protected RealData realData = null;
        protected boolean isReady  false;
        
        public synchronized void setRealData(RealData realData){
             if(isReady ){
                 return;
            }
             this.realData = realData;
             this.isReady = true;
             this.notifyAll();
        }
        @Override
        public synchronized String getResult() {
             // TODO Auto-generated method stub
             while(!isReady ){
                 try{
                     this.wait();
                } catch(InterruptedException ex){
                    ex.printStackTrace();
                }
            }
             return realData .result;
        }
    }
    RealData.java
    public class RealData implements Data{
        protected final String result ;
        public RealData(String queryStr) {
             // TODO Auto-generated constructor stub
            StringBuffer sb = new StringBuffer();
             for(int i = 0; i< 10; i++){
                sb.append(i);
                 try {
                    Thread. sleep(1000);
                } catch (InterruptedException e) {
                     // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
             result = sb.toString();
        }
        @Override
        public String getResult() {
             // TODO Auto-generated method stub
             return this .result ;
        }
    }
    以上就是整个的 Future模式
    JDK 中对于Future是有内部实现的 ,在JDK 中已经内置了一种 future模式实现。 JDK的实现是相当的复杂的,并且提供了更为丰富的多线程控制功能。其中的模块包括:
        Runnable    Future  RunnableFuture FutureTask Sync  Callable
         最为重要的模块式 FutureTask类,他实现了 Runnable接口,作为单独的线程运行。其中 rn方法中通过 Sync内部类,调用 Callable接口返回对象。当使用 FutureTask.get方法的时候,将返回 Callable接口的返回对象。
        Callable 接口是一个用户自己定义的实现,在应用程序中实现 Callable中的 call方法,指定 FutureTask中实际的工作内容和返回对象。
    public class TestMain {
        public static void main(String[] args) throws InterruptedException, ExecutionException  {
             // TODO Auto-generated method stub
            FutureTask<String> future = new FutureTask<String>(new RealData("name"));
            ExecutorService executor = Executors. newFixedThreadPool(1);
            executor.submit(future);
            System. out.println("request finished" );
            
             try {
                Thread. sleep(2000);
            } catch (InterruptedException e) {
                 // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            System. out.println("Data = " + future.get());
        }
    }
    public class RealData implements Callable<String>{
        protected final String para ;
        public RealData(String queryStr) {
             // TODO Auto-generated constructor stub
             this.para = queryStr;
        }
        @Override
        public String call() throws Exception {
             // TODO Auto-generated method stub
            StringBuffer sb = new StringBuffer();
             for(int i = 0; i< 10; i++){
                sb.append(i);
                 try {
                    Thread. sleep(200);
                } catch (InterruptedException e) {
                     // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
             return sb.toString();
        }
    }
         这里使用了线程池技术,从线程翅中获取一个线程,使用他,执行 Callable中的 call函数,返回结果。
         其中ExecutorService executor = Executors.newFixedThreadPool(int);建立一个线程池,初始化线程,然后将任务提交到线程池中使用的是 exector.submit(future);其中future 是实现了Callable call接口,并且具有指定的返回值类型,使用 future.get()获得返回值。
    还就是 FutureTask<ReturnType> future = new FutureTask<ReturnType> (new CallableClass());
        
    当然是可以将 future传递给 Thread的,使用 thread执行 call中的内容,初始化 Callable FutureTask对象,创建一个线程将 futuretask作为线程构造函数的参数,然后是启动刚刚创建的新的线程
        public class FutureTaskDemo {
        public static void main(String[] args) {
             // 初始化一个Callable对象和 FutureTask对象
            Callable pAccount = new PrivateAccount();
            FutureTask futureTask = new FutureTask(pAccount);
             // 使用futureTask 创建一个线程
            Thread pAccountThread = new Thread(futureTask);
            System. out.println("futureTask 线程现在开始启动,启动时间为: " + System.nanoTime());
            pAccountThread.start();
            System. out.println(" 主线程开始执行其他任务 ");
             // 从其他账户获取总金额
             int totalMoney = new Random().nextInt(100000);
            System. out.println(" 现在你在其他账户中的总金额为 " + totalMoney);
            System. out.println(" 等待私有账户总金额统计完毕 ...");
             // 测试后台的计算线程是否完成,如果未完成则等待
             while (!futureTask.isDone()) {
                 try {
                    Thread. sleep(500);
                    System. out.println(" 私有账户计算未完成继续等待 ...");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System. out.println("futureTask 线程计算完毕,此时时间为 " + System.nanoTime());
            Integer privateAccountMoney = null;
             try {
                privateAccountMoney = (Integer) futureTask.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
            System. out.println(" 您现在的总金额为: " + totalMoney + privateAccountMoney.intValue());
        }
    }
     
    @SuppressWarnings("all" )
    class PrivateAccount implements Callable {
        Integer totalMoney;
     
        @Override
        public Object call() throws Exception {
            Thread. sleep(5000);
             totalMoney = new Integer(new Random().nextInt(10000));
            System. out.println(" 您当前有 " + totalMoney + " 在您的私有账户中 ");
             return totalMoney ;
        }
     
    }
     
    TengfeiYang
    于广州中山大学图书馆
    20131114
      
  • 相关阅读:
    PHP中使用Redis
    找回Xcode7的代码折叠功能
    使用 Kingfisher 处理网络图片的读取与缓存
    Swift的两个小窍门
    斯坦福公开课:Developing IOS 8 App with Swift(1-3)心得体会
    What is the relationship between Xcode, Swift and Cocoa?
    C++中static用法总结
    C++中const用法总结
    数据库概念要点
    虚拟内存地址和物理内存地址
  • 原文地址:https://www.cnblogs.com/hbhzsysutengfei/p/3438850.html
Copyright © 2020-2023  润新知