本章重点介绍的是基于 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
  

Java 进阶7 并发优化 1 并行程序的设计模式的更多相关文章

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

    Java进阶7 并发优化2 并行程序设计模式20131114 1.Master-worker模式 前面讲解了Future模式,并且使用了简单的FutureTask来实现并发中的Future模式.下面介 ...

  2. Java进阶7并发优化4——JDK并发数据结构

    Java进阶7并发优化4——JDK并发数据结构20131114 由于并发程序和串行程序的不同特点,在串行程序中使用的数据结构可能无法在并行程序中直接的正常使用,因为这些数据结构可能不是线程安全的,所以 ...

  3. Java 进阶7 并发优化 5 并发控制板方法

    Java 进阶7 并发优化 5 并发控制板方法 20131114 前言:          Java 中多线程并发程序中存在线程安全的问题,之前学习 Java的同步机制,掌握的同步方法只有一种就是使用 ...

  4. 【JAVA】高并发优化细节点

    高并发优化细节点: 微服务化 如何发现系统瓶颈?   如何高效利用有限内存: 使用基本类型 使用数组,不用集合 自定义map与数据结构   Integer—>int, Set<Intege ...

  5. 【Java进阶】并发编程

    PS:整理自极客时间<Java并发编程> 1. 概述 三种性质 可见性:一个线程对共享变量的修改,另一个线程能立刻看到.缓存可导致可见性问题. 原子性:一个或多个CPU执行操作不被中断.线 ...

  6. Java 进阶7 并行优化 JDK多任务执行框架技术

    Java 进阶7 并行优化 JDK多任务执行框架技术 20131114          Java 语言本身就是支持多线程机制的,他提供了 Thread 类 Runnable 接口等简单的多线程支持工 ...

  7. 《Java程序性能优化》学习笔记 JVM和并发优化

    第四章 并行程序优化 1.非阻塞同步避免了基于锁的同步的缺陷,无锁算法没有锁竞争带来的系统开销,也没有线程间频繁调度带来的开销.CAS算法:包含3个参数CAS(v,e,n).V表示要更新的变量,E表示 ...

  8. 《Java程序性能优化》之并发优化

    第四章 并行程序优化 1.非阻塞同步避免了基于锁的同步的缺陷,无锁算法没有锁竞争带来的系统开销,也没有线程间频繁调度带来的开销.CAS算法:包含3个参数CAS(v,e,n).V表示要更新的变量,E表示 ...

  9. Java并发程序设计(二)Java并行程序基础

    Java并行程序基础 一.线程的生命周期 其中blocked和waiting的区别: 作者:赵老师链接:https://www.zhihu.com/question/27654579/answer/1 ...

随机推荐

  1. Django REST Framework 学习笔记

    前言: 基于一些不错的RESTful开发组件,可以快速的开发出不错的RESTful API,但如果不了解开发规范的.健壮的RESTful API的基本面,即便优秀的RESTful开发组件摆在面前,也无 ...

  2. 关于jQuery获得表单radio类型输入框的选中值

    var item=$("input[name='w1']checked").val(); 下面这句,问题解决(加上[type='radio']:): var item=$(&quo ...

  3. HDFS只支持文件append操作, 而依赖HDFS的HBase如何完成数据的增删改查

    转:http://www.th7.cn/db/nosql/201510/135382.shtml 1. HDFS的文件append功能 早期版本的HDFS不支持任何的文件更新操作,一旦一个文件创建.写 ...

  4. imx6q android 添加开机启动脚本

    1.在xx/out/target/product/sabresd_6dq/root/init.rc中添加以下内容 ========================================== ...

  5. 重写(overwrite)、重载(overload)和覆盖(override)三者之间的区别

    覆盖:子类继承了父类的同名无参函数.当子类从父类继承了一个无参函数,而又定义了一个同样的无参函数,则子类定义的方法覆盖父类的方法,称为覆盖. 重载:子类继承了父类的同名有参函数.当子类继承了父类的一个 ...

  6. HBase安装过程

    1).上传,解压,重命名,修改环境变量/etc/profile 2).修改 hbase-env.sh 文件 export JAVA_HOME=/usr/java/jdk1.7.0_27 //Java ...

  7. Hibernate的懒加载session丢失解决方法

    在web.xml加入spring提供的过滤器,延长session的生命周期 <!--Hibernate的懒加载session丢失解决方法 --> <filter> <fi ...

  8. Python学习札记(十七) 高级特性3 列表生成式

    参考:列表生成式 Note 1.List Comprehensions,即列表生成式,是Python中内置的非常强大的list生成式. eg.生成一个列表:[1*1, 2*2, ..., 10*10] ...

  9. PAT1072. Gas Station (30)

    题目的测试用例数据有问题! 第一个Case 应该是 G1 2.0 3.2 一直在想3.3分母的3怎么来了.ORZ #include <iostream> #include <ccty ...

  10. python 使用getopt 获取配置参数

    在工程中特别是稍微大一点的项目基本上都会用到配置,就会涉及到配置文件的读取,配置参数的读取. 常用的解析配置文件的是configParser,解析命令行参数的则为getopt. getopt的参数可以 ...