CoreJava 笔记总结-第十二章 并发-2

文章目录

  • 第十二章 并发
      • `synchronized`关键字
      • 同步块
      • 监视器概念
      • `volatile`字段
      • `final`变量
      • 原子性
      • 死锁
    • 线程安全的集合
    • 阻塞队列
      • 映射条目的原子更新
      • 对并发散列映射的批操作
      • 并行数组算法
      • 同步包装器
    • 任务和线程池
      • `Callable, Future`
      • `Executor`执行器
      • `fork-in`框架
    • 异步计算
      • 可完成`Future`
      • 组合可完成`Future`
    • 进程
      • 建立一个进程

第十二章 并发

synchronized关键字

  • 锁用来保护代码片段,一次只能有一个线程执行被保护代码
  • 锁可以管理试图进入被保护代码段的线程
  • 一个锁可以有一个或者多个相关联的条件对象
  • synchronized,设置内部锁
  • wait方法将线程增加到等待集中
  • notifyAll, notify方法可以接触等待线程的阻塞

同步块

  • 会获得obj
synchronized(obj){critical section
}
  • public class Bank{private double[] accounts;private var lock = new Object();public void transfer(int from, int to, int amount){synchronized(lock){accounts[from] -= amount;accounts[to] += amount;}System.out.println(...)}
    }
    
  • 程序员用一个对象锁实现额外的原子操作,称为客户端锁定(十分脆弱)


监视器概念

  • 监视器特性:
  1. 只包含私有字段
  2. 每个对象都有一个关联的锁
  3. 所有的方法由这个锁锁定 (客户端调用object,method(), object对象的方法调用开始时自动获得锁,方法返回时自动释放,这样可以确保一个线程处理字段时,没有其余的线程能够访问这些字段)
  4. 锁可以有任意多个相关联的条件

volatile字段

  • 为实例字段的同步访问提供了一中免锁机制
  • 下例使用内部锁.如果另一个线程已经为该对象加锁,两种方法可能被阻塞
private boolean done;
public synchronized boolean isDone(){ return done;}
public synchronized void setDone() {done = true;}

---->

private volatile boolean done;
public boolean isDone(){ return done;}
public void setDone() {done = true;}

final变量

  • final var accounts = new HashMap<String, Double>();其他线程会在构造器完成之后才看到accounts变量

原子性

  • 对共享变量除了赋值不做其他操作,可以声明为volatile
  • java.util.concurrent.atomic包中很多类保证原子性操作
  • AtomicInteger类提供方法incrementAndGet, decrementAndGet分别以原子方式对一个整数进行自增或者自减

死锁

  • P584
  • 当两个线程互相操作且互相操作不能进行,形成死锁

线程安全的集合

阻塞队列

  • 使用队列可以安全的从一个线程向另一个线程传递数据
  • 当试图向队列中添加元素且队列已满,或者从队列中移除元素而队列已空,阻塞队列将导致线程阻塞
  • put, take方法: 向队列中添加或者移除元素,队列满或者空就阻塞,与不带超时参数的方法offer, poll等效

映射条目的原子更新

  • ConcurrentHashMap类中compute方法可以提供一个键和一个计算新值的函数,比如可以更新一个整数计数器的映射
map.compute(word, (k, v) -> v == null ? 1 : v + 1);
  • computeIfAbsent, computeIfPresent分别只在没有原值和有原值的情况下计算新值
map.compyteIfAbsent(word, k -> new LongAdder()).increment();
  • merge方法表示一个参数键不存在的时候提供初始值,存在就调用提供的函数结合初始值和原值
map.merge(word, 1L, (existingValue, newValue) -> existingValue+newValue);
//简便形式
map.merge(word, 1L, Long::sum);

对并发散列映射的批操作

  • 即使有其他线程在处理映射,批操作也能安全执行
  • search, reduce, forEach操作,可以operation, operationKeys, operationValues, operationEntries分别处理键和值,处理键,处理值,处理Map.Entry对象
  • 需要指定一个参数化阈值,映射包含元素多于这个值就会进行批操作
U searchKeys(long threshold, BiFunction<? super K, ? extends U> f)
U searchValues(long threshold, BiFunction<? super K, ? extends U> f)
U search(long threshold, BiFunction<? super K, ? extends U> f)
U searchEntries(long threshold, BiFunction<? super K, ? extends U> f)
  • 搜索超过一百次出现的单词
String result = map.search(threshold, (k, v) -> v > 1000 ? k : null);

并行数组算法

  • P601

同步包装器

  • 任何集合类都可以通过使用同步包装器变成线程安全的
List<E> synchArray  = Collections.synchronizedList(new ArrayList<E>());
Map<K, V> synchHashMap = Collections.synchroniedHashMap(new HashMap<K, V>());

任务和线程池

Callable, Future

  • Runnable封装一个异步运行的任务, 没有参数和返回值的异步方法
  • Callable有返回值,和前者类似,该接口是一个参数化类型,只有一个方法call
public interface Callable<V>{V call() throws Exception;
}
  • Future保存异步计算的结果

  • 执行Callable方法之一是使用FutureTask. 它实现了Future, Runnable接口,所以可以构造一个线程运行该任务

Callable<Integer> task = ;
var FutureTask = new FutureTask<Integer>(task);
var t = new Thread(futureTask);
t.start();
...
Integer result = task.get(); //it's a Future

Executor执行器

  • newCachedThreadPool构造一个线程池,必要时创建新线程,空闲状态可以保持六十秒
  • newFixedThreadPool构造一个具有固定大小的线程池;提交任务数量大于线程数,放到队列中,任务完成后再运行排队的任务
  • newSingleThreadExecutor只有一个线程的池,顺序执行提交的任务
  • 并发线程数量=处理器内核数 为最优的运行速度
  • 提交任务Future<T> submit(Callable<T>, task)
  • 结束线程池shutdown
    public static void main(String[] args)throws InterruptedException, ExecutionException, IOException{try (var in = new Scanner(System.in)){System.out.print("Enter base directory (e.g. /opt/jdk-9-src): ");String start = in.nextLine();System.out.print("Enter keyword (e.g. volatile): ");String word = in.nextLine();Set<Path> files = descendants(Path.of(start));var tasks = new ArrayList<Callable<Long>>();for (Path file : files){Callable<Long> task = () -> occurrences(word, file);tasks.add(task);}ExecutorService executor = Executors.newCachedThreadPool();// use a single thread executor instead to see if multiple threads// speed up the search// ExecutorService executor = Executors.newSingleThreadExecutor();Instant startTime = Instant.now();List<Future<Long>> results = executor.invokeAll(tasks);long total = 0;for (Future<Long> result : results)total += result.get();Instant endTime = Instant.now();System.out.println("Occurrences of " + word + ": " + total);System.out.println("Time elapsed: "+ Duration.between(startTime, endTime).toMillis() + " ms");var searchTasks = new ArrayList<Callable<Path>>();for (Path file : files)searchTasks.add(searchForTask(word, file));Path found = executor.invokeAny(searchTasks);System.out.println(word + " occurs in: " + found);if (executor instanceof ThreadPoolExecutor) // the single thread executor isn'tSystem.out.println("Largest pool size: "+ ((ThreadPoolExecutor) executor).getLargestPoolSize());executor.shutdown();}}

fork-in框架

  • P612

异步计算

可完成Future

  • 当有一个Future对象会调用get来获得值,这个方法会阻塞直到值可用
  • CompletableFuture类实现了Future接口,注册回调,一旦结果可用,就会在某个线程中调用这个回调,无需阻塞
  • 被称为可完成的,是因为可以手动设置一个完成值,这样的对象在其他并发库中称为承诺
var f = new CompletableFuture<Integer>();
excutor.excute(() -> {int n = workHard(arg);f.complete(n);
});
excutor.excute(() -> {int n = workSmart(arg);f.complete(n);
}) ;
  • 对一个异常完成Future
Throwable t = ...;
f.completeExceptionally(t);

组合可完成Future

  • 非阻塞调用通过回调来实现
  • 程序员为任务完成后要出现的动作注册一个回调
  • 函数thenCompose组合函数T->CompletableFuture<U> 和U -> CompletableFuture<V>
  • whenComplete方法用于处理异常,还有handle方法,他需要一个函数处理结果或者异常,并且计算一个新结果

进程

  • Process类在一个单独的操作系统中执行一个命令,允许我们标准输入.输出和错误流交互
  • ProcessBuilder类允许配置Process对象

建立一个进程

  • 用命令和参数构建一个进程构建器

  • var builder = new Process

  • Builder("gcc", "myapp.c");

  • 第一个字符串必须是一个可执行命令

  • 改变工作目录

builder = builder.directory(path.toFile());
  • 处理进程的标准输入流,输出和错误流
OutputStream processIn = p.getOutputStream();
IntputStream processOut = p.getInputStream();
IntputStream processErr = p.getErrorStream();
  • Attention: 进程的输入流是jvm的一个输出流,进程将输出展示到控制台上
  • startPipeLine利用管道将一个进程的输入作为另一个进程的输出

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/311368.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

八数码问题II-bfs和map标记

问题描述&#xff1a; 在33的棋盘上&#xff0c;摆有八个棋子&#xff0c;每个棋子上标有1至8的某一数字。棋盘中留有一个空格&#xff0c;空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是&#xff1a; 给出一种初始布局&#xff08;初始状态&#xff09;和目标布…

华为任职资格_看了华为的任职资格体系,你就明白员工为啥这么拼?

提到华为的18万奋斗者&#xff0c;职场上没人不竖起大拇指。而优秀人才的背后&#xff0c;就像任正非曾说过的那样&#xff0c;华为的成功&#xff0c;很大意义上讲就是人力资源的成功。华为的人力资源管理最有代表性的&#xff0c;除了狼性文化和薪酬绩效外&#xff0c;就是任…

如何使用有序GUID提升数据库读写性能

源宝导读&#xff1a;数据库设计时&#xff0c;经常会使用GUID作为表的主键&#xff0c;但由于GUID的随机性会导致数据库在读写数据时效率严重下降&#xff0c;影响应用程序整体性能。本文将深入探讨如何通过使用有序GUID提升数据读写的性能。一、背景常见的数据库设计是使用连…

八数码问题II-双向bfs和map标记

问题描述&#xff1a; 在33的棋盘上&#xff0c;摆有八个棋子&#xff0c;每个棋子上标有1至8的某一数字。棋盘中留有一个空格&#xff0c;空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是&#xff1a; 给出一种初始布局&#xff08;初始状态&#xff09;和目标布…

MarkDown语法, 快捷键,Dos命令

文章目录MarkDown 语法计算机软件快捷键Dos命令MarkDown 语法 字体: 斜体, 粗体, 删除图片: ![title](link)超链接: [words](link)引用>标题列表表格 名字|性别|生日 31辅导班VS看复旦南开都是vs1ds代码块 分割线*** 计算机软件 系统软件应用软件DOS, Windows, Unix,…

《商业洞察力30讲》学习笔记(上)

【洞察力】| 作者 / Edison Zhou这是恰童鞋骚年的第197篇原创文章学习洞察力&#xff0c;也是新时代IT人员的一门进阶必修课...1学习背景2019年下半年至今&#xff0c;在领导的推荐下学习了刘润老师的《商业洞察力30讲》&#xff0c;刷新了我对于事物的认知&#xff0c;也为我提…

[蓝桥杯][历届试题]九宫重排-双向bfs和map标记

题目描述 如下面第一个图的九宫格中&#xff0c;放着 1~8 的数字卡片&#xff0c;还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动&#xff0c;可以形成第二个图所示的局面。 我们把第一个图的局面记为&#xff1a;12345678. 把第二个图的局面记…

3月数据库排行:前10整体下行,出新技术了?

DB-Engines 数据库流行度排行榜 3 月更新已发布&#xff0c;排名前二十如下&#xff1a;排名方面没有任何变动&#xff08;仅针对前十&#xff09;&#xff0c;相信很长一段时间内也都不会变动&#xff0c;毕竟巨头的位置不是一时半刻就能动摇的。不过这个月的排行榜还是有值得…

CSS3动画大全(附源码)flex布局,grid布局3d旋转,图像模糊,文字发光

CSS3动画大全(附源码)3d旋转,图像模糊,文字发光! 文章目录CSS3动画大全(附源码)3d旋转,图像模糊,文字发光!html代码cssgrid布局flex布局文字发光 & 图像放缩3d旋转 图像移动源码html代码 <body><div class"container"><div class"main"…

每日一题——LeetCode160.相交链表

个人主页&#xff1a;白日依山璟 专栏&#xff1a;Java|数据结构与算法|每日一题 文章目录 1. 题目描述示例1&#xff1a;示例2&#xff1a;提示&#xff1a; 2. 思路3. 代码 1. 题目描述 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的…

[蓝桥杯][2013年第四届真题]买不到的数目-模拟,数论

题目描述 小明开了一家糖果店。他别出心裁&#xff1a;把水果糖包成4颗一包和7颗一包的两种。糖果不能拆包卖。 小朋友来买糖的时候&#xff0c;他就用这两种包装来组合。当然有些糖果数目是无法组合出来的&#xff0c;比如要买 10 颗糖。 你可以用计算机测试一下&#xff0c;在…

.NET Core的HttpClient连接池管理

译者荐语&#xff1a;使用.NET Core的HttpClient连接池管理有哪些注意事项&#xff1f;本文给出了非常中肯的建议。原文来自互联网&#xff0c;由长沙DotNET技术社区编译。如译文侵犯您的署名权或版权&#xff0c;请联系小编&#xff0c;小编将在24小时内删除。本文来源[1]史蒂…

[蓝桥杯][2014年第五届真题]兰顿蚂蚁-模拟

题目描述 兰顿蚂蚁&#xff0c;是于1986年&#xff0c;由克里斯兰顿提出来的&#xff0c;属于细胞自动机的一种。 平面上的正方形格子被填上黑色或白色。在其中一格正方形内有一只“蚂蚁”。 蚂蚁的头部朝向为&#xff1a;上下左右其中一方。 蚂蚁的移动规则十分简单&#…

.NET Core开发实战(第17课:为选项数据添加验证:避免错误配置的应用接收用户流量)--学习笔记...

17 | 为选项数据添加验证&#xff1a;避免错误配置的应用接收用户流量三种验证方法1、直接注册验证函数2、实现 IValidateOptions3、使用 Microsoft.Extensions.Options.DataAnnotations延用上一节代码需要添加验证的时候不能用 Configure&#xff0c;而用 AddOptions 方法//se…

[蓝桥杯][2014年第五届真题]分糖果-模拟

题目描述 问题描述 有n个小朋友围坐成一圈。老师给每个小朋友随机发偶数个糖果&#xff0c;然后进行下面的游戏&#xff1a; 每个小朋友都把自己的糖果分一半给左手边的孩子。 一轮分糖后&#xff0c;拥有奇数颗糖的孩子由老师补给1个糖果&#xff0c;从而变成偶数。 反复进…

分支程序与循环程序设计-汇编实验二

DATA SEGMENT ;定义数据段BUF DB -1, 20, 3, 30, -5, 15, 100, -54, 0, 4, 78, 99DB -12, 32, 3, 23, -7, 24, 60,-51 ;定义比较大小的数据DATA ENDS ;数据段结束ESEG SEGMENT ;定义附加段RES1 DB 0;定义结果存放区RES2 DB 0RES3 DB 0 ESEG ENDS ;附加段结束CODE SEGMENT ;定义…

[蓝桥杯][2013年第四届真题]剪格子-dfs

题目描述 历届试题 剪格子 时间限制&#xff1a;1.0s 内存限制&#xff1a;256.0MB 问题描述 如下图所示&#xff0c;3 x 3 的格子中填写了一些整数。 我们沿着图中的星号线剪开&#xff0c;得到两个部分&#xff0c;每个部分的数字和都是60。 本题的要求就是请你编程判定&a…

使用有序GUID:提升其在各数据库中作为主键时的性能

原文出处&#xff1a;https://www.codeproject.com/articles/388157/guids-as-fast-primary-keys-under-multiple-database &#xff0c;避免今后忘记了再去阅读原英文。【】是感觉理解有问题的地方正确的使用有序GUID在大部分数据库中可以获得和 整型作为主键 时相媲美的性能。…

串操作指令及其应用程序的设计与调试运行——汇编实验四 用8086汇编完成下题 编制一程序,从键盘输入两个长度不同的字符串,设字符串长度小于25个字符。要求在屏幕上以右边对齐的形式显示出

文章目录实验目的和内容实验要求和步骤实现右对齐以下为源码&#xff1a;方法一方法二方法三测试一——字符串的输入输出测试二——改进测试三——改进测试四——改进实验目的和内容 实验要求和步骤 实现右对齐 以下为源码&#xff1a; 方法一 DATA SEGMENTNUM EQU 25BUF1 D…

python 语音播放_基于Python编写的语音播放软件

单位经常使用广播进行临时事项的通知(将文字转换为语音然后通过功放广播)&#xff0c;但是市面上多数语音播放软件都是收费的&#xff0c;要么发音失真&#xff0c;要么不够稳定——经常出现莫名其妙的故障&#xff0c;容易给工作带来被动。学Python这么久不如动手写一款自己的…