第五章 并行模式与算法

1、单例模式

  • 是一种对象创建模式,用于产生一个对象的具体实例,它可以确保系统一个类只产生一个实例。
  • 对于频繁创建使用的对象可以省略new 操作花费的时间,可以减少系统开销。
  • 由于new 操作的次数减少,系统内存使用频率降低,这将减轻GC压力,缩短GC停顿时间。
  • 构造函数私有,instance对象需要是私有且静态的

2、不变模式

核心:一个对象一旦被创建,则它的内部状态将永远不会发生改变。

不变模式的实现:

  • 去除所有的setter方法以及所有修改自身属性的方法。
  • 属性设为私有,并且final标记,确保其不可修改。
  • 确保子类可以重载修改它的行为。
  • 有一个可以创建完整对象的构造函数。

使用不变模式的例子:元数据的包装类和String类

3、生产者消费者模式

  • 生产者线程负责提交用户请求,消费者线程负责具体处理生产者提交的任务,生产者和消费者之间则通过共享内存缓冲进行通信。
  • 生产者消费者模式中的内存缓存区,它做为生产者消费者之间的通信桥梁,避免了生产者和消费者之间的直接通信,从而将生产者和消费者进行解耦。
  • 缓冲区的主要功能是数据在多线程间的共享,此外通过该缓冲区可以缓解生产者和消费者间的性能差异。

    共享数据:

    package com.ecut.pattern;
    
    public class PCData {
    
        private final int intData;
    
        public PCData(String s) {
    intData = Integer.valueOf(s);
    } public PCData(int i) {
    intData = i;
    } @Override
    public String toString() { return "PCdata:" + intData;
    }
    }

    生产者:

    package com.ecut.pattern;
    
    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.atomic.AtomicInteger; public class Producer implements Runnable { private volatile boolean isRunning = true; private AtomicInteger count = new AtomicInteger(); private BlockingQueue<PCData> queue; public Producer(BlockingQueue<PCData> queue) {
    this.queue = queue;
    } @Override
    public void run() {
    while (isRunning) {
    PCData data = new PCData(count.incrementAndGet());
    if (!queue.offer(data)) {
    System.out.println(Thread.currentThread().getName() + "failed to put data:" + data);
    } else {
    System.out.println(Thread.currentThread().getName() + " product data :" + data);
    }
    }
    } public void stop() {
    isRunning = false;
    }
    }

    消费者:

    package com.ecut.pattern;
    
    import java.util.concurrent.BlockingQueue;
    
    public class Consumer implements Runnable {
    
        private BlockingQueue<PCData> queue;
    
        public Consumer(BlockingQueue<PCData> queue) {
    this.queue = queue;
    } @Override
    public void run() {
    try {
    while (true) {
    PCData pcData = queue.take();
    if (pcData != null) {
    System.out.println(Thread.currentThread().getName() + " consumer data " + pcData);
    }
    }
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }

    Main函数:

    package com.ecut.pattern;
    
    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.LinkedBlockingDeque; public class Main { public static void main(String[] args) throws InterruptedException {
    BlockingQueue<PCData> blockingQueue = new LinkedBlockingDeque<PCData>(10);
    Producer producer1 = new Producer(blockingQueue);
    Producer producer2 = new Producer(blockingQueue);
    Producer producer3 = new Producer(blockingQueue);
    Consumer consumer1 = new Consumer(blockingQueue);
    Consumer consumer2 = new Consumer(blockingQueue);
    Consumer consumer3 = new Consumer(blockingQueue);
    ExecutorService executorService = Executors.newCachedThreadPool();
    executorService.execute(producer1);
    executorService.execute(producer2);
    executorService.execute(producer3);
    executorService.execute(consumer1);
    executorService.execute(consumer2);
    executorService.execute(consumer3);
    Thread.sleep(10000);
    producer1.stop();
    producer2.stop();
    producer3.stop();
    executorService.shutdown();
    }
    }

4、Future模式

  • Future模式的核心是异步调用,可以被调用者立即返回,让他在后台慢慢处理这个请求。调用者可以先处理其他任务。
  • RunnableFuture继承了Future和Runnable接口,其中run方法用于构造真实数据,它有一个具体实现类FutureTask类。FutureTask类内部run方法使调用Callable接口的run方法。
    package com.ecut.pattern;
    
    import java.util.concurrent.Callable;
    
    public class RealData implements Callable<String> {
    private String para; public RealData(String para) {
    this.para = para;
    } @Override
    public String call() throws Exception {
    StringBuffer stringBuffer = new StringBuffer();
    for(int i = 0 ; i< 10 ; i++){
    stringBuffer.append(para);
    }
    return stringBuffer.toString();
    }
    }

    FutureTest类:

    package com.ecut.pattern;
    
    import java.util.concurrent.*;
    
    public class FutureTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
    //构造futureTask
    FutureTask<String> futureTask = new FutureTask<String>(new RealData("a"));
    ExecutorService executorService = Executors.newSingleThreadExecutor();
    //执行futureTask实际上是调用的RealData的call方法
    executorService.submit(futureTask);
    System.out.println("请求完毕!");
    //异步调用,因此这里可以进行其他的业务处理
    Thread.sleep(2000);
    //如果call方法没有执行完则依然等待
    System.out.println("数据为" + futureTask.get());
    }
    }

    运行结果如下:

    请求完毕!
    数据为aaaaaaaaaa

5、并行流水线

并行流水线:将有依赖的操作分配在不同的线程进行计算。

package com.ecut.parallel;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue; public class Pipeline { public static class Msg {
public double i;
public double j;
public String orgStr = null;
} public static class Plus implements Runnable { public static BlockingQueue<Msg> blockingQueue = new LinkedBlockingQueue<>(); @Override
public void run() {
try {
Msg msg = blockingQueue.take();
msg.j = msg.i + msg.j;
Multiply.blockingQueue.add(msg);
} catch (InterruptedException e) {
e.printStackTrace();
} }
} public static class Multiply implements Runnable { public static BlockingQueue<Msg> blockingQueue = new LinkedBlockingQueue<>(); @Override
public void run() {
try {
Msg msg = blockingQueue.take();
msg.j = msg.j * msg.i;
Div.blockingQueue.add(msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} public static class Div implements Runnable { public static BlockingQueue<Msg> blockingQueue = new LinkedBlockingQueue<>(); @Override
public void run() {
try {
Msg msg = blockingQueue.take();
msg.j = msg.j / 2;
System.out.println(msg.orgStr + "=" + msg.j);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} public static void main(String[] args) {
for (int i = 1; i < 1000; i++) {
for (int j = 1; j < 1000; j++) {
Msg msg = new Msg();
msg.i = i;
msg.j = j;
msg.orgStr = "((" + i + "+" + j + ")" + "*" + i + ")/2";
Plus.blockingQueue.add(msg);
new Thread(new Plus()).start();
new Thread(new Multiply()).start();
new Thread(new Div()).start();
}
} }
}

6、并行排序

例子:奇偶排序、希尔排序

源码地址:

https://github.com/SaberZheng/concurrent-test

转载请于明显处标明出处:

https://www.cnblogs.com/AmyZheng/p/10481967.html

《实战Java高并发程序设计》读书笔记五的更多相关文章

  1. 【鸟哥的Linux私房菜】笔记1

    Linux是什么 从操作系统与cpu架构关系到linux  Richard Mathew Stallman GPL 关于GNU计划 Linux的发展 Linux的核心版本 Linux的特色 Linux ...

  2. 【鸟哥的Linux私房菜】笔记3

    正确地开机 最好不要使用root账号登陆!GNOME图形界面 View items as a list X WindowShell 文本交互界面bash是Shell的名称,Linux的默认壳程序就是b ...

  3. 【鸟哥的Linux私房菜】笔记2

    Linux的应用 学习资源整理 安装记录 >< 1.Linux的应用: 网络服务器 数据库 学术机构的高效运算任务 嵌入式系统 ... 2.挂载与磁盘分区 学习资源整理 学习 1.书上的网 ...

  4. 《鸟哥的Linux私房菜》笔记——02. 关于Linux

    Unix 历史 1969年以前:伟大的梦想--Bell, MIT 与 GE 的「Multics」系统 1969年:Ken Thompson 的小型 file server system 1973年:U ...

  5. 《鸟哥的Linux私房菜》笔记——03. 磁盘分区

    Everything is a file. 常见硬件对应于 Linux 下的文件(/dev目录下) 装置 装置在Linux内的档名 SCSI/SATA/U盘硬盘机 /dev/sd[a-p] U盘 /d ...

  6. 鸟哥的linux私房菜学习笔记 __ 命令与文件的搜寻

    连续输入两次[tab]按键就能够知道使用者有多少命令可以下达.那你知不知道这些命令的完整档名放在哪里?举例来说,ls 这个常用的命令放在哪里呢? 就透过 which 或 type 来找寻吧! 范例一: ...

  7. 【鸟哥的Linux私房菜】笔记

    操作系统核心的功能! 驱动程序与操作系统的关系 2. [计算机组成之组件] 3.CPU实际要处理的数据完全来自于主存储器,这是一个很重要的概念! 4.CPU是整个计算机系统最重要的部分,那么目前世界上 ...

  8. 《鸟哥的Linux私房菜》笔记——04. 简单命令行

    键入命令 [dmtsai@study ~]$ command [-options] parameter1 parameter2 ... 指令 選項 參數(1) 參數(2) 注意:有时也可以使用 + 放 ...

  9. 鸟哥的Linux私房菜学习笔记——文件权限与目录配置

    Linux的文件权限和目录配置 在linux中的每个用户必需属于一个组,不能独立于组外.在linux中每个文件有所有者.所在组.其它组的概念. (1)所有者 一般为文件的创建者,谁创建了该文件,就是天 ...

  10. 鸟哥的Linux私房菜学习笔记(1)

    2014/10/29 1.档案的权限管理分为三个部分: 拥有者.群组.其他 2.ls -al 命令可以看到档案的详细信息 3.档案的属性中由十个部分构成 第一个部分是档案类型 -代表档案.d代表文件夹 ...

随机推荐

  1. Outlook365(Oulook2016 或2013) 写邮件输入收件人时的推荐联系人如何清理?

    · 在Outlook365(Oulook2016 或2013) 中写邮件,输入收件人邮箱地址时,会出现“最近联系人”  “其他建议”等推荐的联系人,可以方便选择.如果里面有很多邮箱地址的已经无效的话, ...

  2. Python之路Day01

    一.Python简介 Python的历史 Python 2.4 - November 30, 2004, 同年目前最流行的WEB框架Django 诞生 In November 2014, it was ...

  3. nginx的错误处理

    以下是针对nginx发生错误的处理方案(将会持续更新) 遇到 nginx: [error] invalid PID number "" in "/var/run/ngin ...

  4. Entity Framework 简介

    Entity Framework Entity Framework 的全称为 ADO.NET Entity Framework,简称 EF. 1.与 ADO.NET 的关系      Entity F ...

  5. HTML的图像标签

    网页的图像标签 常见的图像格式 JPG GIF PNG BMP 图像标签可以带属性,格式为: <img src="path" alt="text" tit ...

  6. Python入门3 —— 基本数据类型

    一:为何变量值(记录的数据)要有类型呢? 1.既然可以记录事物的状态,为什么要分类型呢? 变量值是来记录事物状态的, 而事物的状态是多种多样的, 所以对应着就要应该用不同类型的值去记录这些状态. 二: ...

  7. 常见运算符_python

    一.算数运算符a=2b=5c=8#加减乘除print(a+b,a-b,a*b,a/b)#取模,也就是余数print(b%a)#取整除print(b//a)#幂(次方)print(b**a) 二.比较运 ...

  8. flutter_html 和 WebView 解析html 和 build.gradle源码

    一.flutter_html 涉及的 api 接口: http://www.phonegap100.com/appapi.php?a=getPortalArticle&aid=20 二.Flu ...

  9. 【C语言】输入一个字符串,并对字符串中的偶数位置的字符按从小到大的顺序排序,奇数位置的字符不动,输出排序后的结果

    #include <stdio.h> #include<string.h> int main() { ]; int i,j,k,len; gets_s(a); len= str ...

  10. Verilog 编写规范

    在学习Python时,作者有一句话对我影响很大.作者希望我们在学习编写程序的时候注意一些业内约定的规范.在内行人眼中,你的编写格式,就已经暴露了你的程度.学习verilog也是一样的道理,一段好的ve ...