并发
文章平均质量分 77
sunhaoning
这个作者很懒,什么都没留下…
展开
-
《Java高并发程序设计》学习 --7.1 Akka之Hello World
首先看一下,第一个Actor的实现:public class Greeter extends UntypedActor { public static enum Msg { GREET,DONE; } @Override public void onReceive(Object msg) throws Exception { if(msg ==Msg.GREET) { S原创 2017-04-06 21:33:50 · 2446 阅读 · 0 评论 -
《Java高并发程序设计》学习 --1.3有关并行的两个重要定律
1)Amdahl定律加速比定义:加速比= 优化前系统耗时/优化后系统耗时 根据Amdahl定律,使用多核CPU对系统进行优化,优化的效果取决于CPU的数量以及系统中串行程序的比重。CPU数量越多,串行化比重越低,则优化效果越好。仅提高CPU核数不降低系统串行程序比重,也无法提高系统性能。2)Gustafson定律根据G原创 2017-03-15 09:06:35 · 506 阅读 · 0 评论 -
《Java高并发程序设计》学习 --1.4Java内存模型
1)原子性原子性是指一个操作是不可中断的。即使是在多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程干扰。比如,对于一个静态全局变量int i,两个线程同时对它赋值,线程A给它赋值1,线程B给它赋值为-1。那么不管这2个线程以何种方式、何种步调工作,i的值要么是1,要么是-1、线程A和线程B之间是没有干扰的。这就是原子性的一个特点,不可被中断。但是如果不使用int而使用long原创 2017-03-15 21:20:28 · 376 阅读 · 0 评论 -
《Java高并发程序设计》学习 --5.8 并行排序
1)分离数据相关性:奇偶交换排序对于奇偶交换排序来说,它将排序过程分为两个阶段,奇交换和偶交换。对于奇交换来说,它总是比较奇数索引以及其相邻的后续元素。而偶交换总是比较偶数索引和其相邻的后续元素。并且,奇交换和偶交换会成对出现,这样才能保证比较和交换涉及到数组中的每一个元素。下面是奇偶交换排序的串行实现:public static void oddEvenSort(int[] arr)原创 2017-03-25 09:22:47 · 390 阅读 · 2 评论 -
《Java高并发程序设计》学习 --5.7 并行搜索
对于有序数据,通常可以采用二分查找法。对于无序数据,则只能挨个查找。在本节中,我们将讨论有关并行的无序数组的搜索实现。给定一个数组,我们要查找满足条件的元素。对于串行程序来说,只要遍历一下数组就可以得到结果。但如果要使用并行方式,则需要额外增加一些线程间的通信机制,使各个线程可以有效地运行。一种简单的策略就是将原始数据集合按照期望的线程数进行分割。每个线程各自独立搜索,当其中一个线程找到数原创 2017-03-25 09:18:01 · 382 阅读 · 0 评论 -
《Java高并发程序设计》学习 --5.6 并行流水线
并发算法虽然可以充分发挥多核CPU的性能,但并非所有的计算都可以改造成并发形式。执行过程中有数据相关性的运算都是无法完美并行化的。假如现在有两个数,B和C。如果要计算(B+C)*B/2,那么这个运算过程就是无法并行的。原因是,如果B+C没有执行完成,则永远算不出(B+C)*B,这就是数据相关性。遇到这种情况,可以借鉴日常生产中的流水线思想。类似的思想可以借鉴到程序开发中。即使(B+C)原创 2017-03-25 09:15:53 · 768 阅读 · 0 评论 -
《Java高并发程序设计》学习 --5.5 并行模式之 Future模式
它的核心是异步调用,如果我们不着急要结果,可以让被调用者立刻返回,随后让它在后台慢慢处理这个请求,对于调用者来说则可以处理其他任务,在真正需要数据的场合再去尝试获得需要的结果。1)Future模式的主要角色参与者作用Main系统启动,调用Client发出请求Client返回Data对象,立即返回Futu原创 2017-03-20 19:54:43 · 415 阅读 · 0 评论 -
《Java高并发程序设计》学习 --1.2并发级别
1)阻塞一个线程是阻塞的,那么在其他线程释放资源之前,当前线程无法继续执行。当我们使用synchronized关键字,或者重入锁时,我们得到的就是阻塞的线程。 无论是synchronized还是重入锁,都会在视图执行后续代码前得到临界区的锁,如果得不到,线程就会被挂起等待,直到占有了所需要的资源为止。2)无饥饿如果线程间是有优先级的,那么线程调用总是会倾向于满足高优先级的线原创 2017-03-15 09:03:20 · 925 阅读 · 0 评论 -
《Java高并发程序设计》学习 --6.6 读写锁的改进:StampedLock
StamppedLock是Java 8中引入的一种新的锁机制。读写锁虽然分离了读和写的功能,使得读与读之间可以完全并发。但是,读和写之间依然是冲突的。读锁会完全阻塞写锁,它使用的依然是悲观锁的策略,如果有大量的读线程,它也有可能引起写线程的“饥饿”。而StampedLock提供了一种乐观的读策略。这种乐观策略的锁非常类似无锁的操作,使得乐观锁完全不会阻塞写线程。1)StampedLock使原创 2017-03-31 14:23:15 · 1940 阅读 · 0 评论 -
《Java高并发程序设计》学习 --7.9 询问模式:Actor中的Future
由于Actor之间都是通过异步消息通信的。当发送一条消息给一个Actor后,通常只能等待Actor的返回。与同步方法不同,在发送异步消息后,接受消息的Actor可能还根本来不及处理你的消息,而调用方就已经返回了。这种模式与之前提到的Future模式非常相像。不同之处只是在传统的异步调用中,进行的是函数调用,但在这里,发送了一条消息。public class AskMain { publi原创 2017-04-09 11:34:15 · 634 阅读 · 0 评论 -
《Java高并发程序设计》学习 --2.1 基本概念
1)进程进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。程序是指令、数据及其组织形式的描述,进程是程序的实体。2)线程线程是轻量级进程,是程序执行的最小单位。使用多线程而不是多进程去进行并发程序设计,是因为线程间的切换或调度的成本远小于进程。3)线程的状态:NEW状态表示刚刚创建的线程,这种线程还没原创 2017-03-15 21:30:19 · 248 阅读 · 0 评论 -
《Java高并发程序设计》学习 --2.2 初始线程:线程的基本操作
1)新建线程Java提供了线程类Thread来创建多线程的程序。其实,创建线程与创建普通的类的对象的操作是一样的,而线程就是Thread类或其子类的实例对象。每个Thread对象描述了一个单独的线程。要产生一个线程,有两种方法:◆ 需要从Java.lang.Thread类派生一个新的线程类,重载它的run()方法; ◆ 实现Runnalbe接口,重载Runnalbe接口中的run()方原创 2017-03-15 21:32:34 · 320 阅读 · 0 评论 -
《Java高并发程序设计》学习 --2.3 volatile与Java内存模型(JMM)
volatile的定义如下: java编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致的更新,线程应该确保通过排他锁单独获得这个变量。volatile对于保证操作的原子性是有非常大的帮助的。但是,volatile并不能代替锁,它无法保证一些复合操作的原子性,例如,volatile是无法保证i++的原子性操作的:public class PlusTask {static vo原创 2017-03-15 21:39:06 · 280 阅读 · 0 评论 -
《Java高并发程序设计》学习 --6.7. 原子类的增强
无锁的原子类操作使用系统的CAS指令,有着远远超越锁的性能。在Java 8中引入了LongAddr类,这个类也在java.util.concurrent.atomic包下,因此,它也是使用了CAS指令。1)更快的原子类:LongAddrAtomicInteger的基本实现机制,它们都是在一个死循环内,不断尝试修改目标值,知道修改成功。如果竞争不激烈,那么修改成功的概率就很高,否则,修改失败原创 2017-04-04 19:49:58 · 460 阅读 · 0 评论 -
《Java高并发程序设计》学习 --3.1多线程的团队协作:同步控制
1)synchronized的功能扩展:重入锁重入锁可以完全替代synchronized关键字。在JDK5.0的早期版本,重入锁的性能远远好于synchronized,但从JDK6.0开始,JDK在synchronized上做了大量的优化,使得两者的性能差距并不大。重入锁使用java.util.concurrent.locks.ReentrantLock类来实现,如下代码:import原创 2017-03-17 09:04:01 · 839 阅读 · 0 评论 -
《Java高并发程序设计》学习 --5.11 AIO
虽然NIO在网络操作中,提供了非阻塞的方法,但是NIO的IO行为还是同步的。对于NIO来说,我们的业务线程是在IO操作准备好时,得到通知,接着就由这个线程自行进行IO操作,IO操作本身还是同步的。对于AIO,它不是在IO准备好时再通知线程,而是在IO操作依据完成后,再给线程发出通知。因此,AIO是完全不会阻塞的。此时,我们的业务逻辑将变成一个回调函数,等待IO操作完成后,由系统自动触发。下原创 2017-03-25 20:24:57 · 290 阅读 · 0 评论 -
《Java高并发程序设计》学习 --5.10 网络NIO
JavaNIO中涉及的基础内容有通道(Channel)和缓冲区(Buffer)、文件IO和网络IO。1)基于Socket的服务端的多线程模式这里,以Echo服务器为例。对于Echo服务器,它会读取客户端的一个输入,并将这个输入原封不动地返回给客户端。服务器会为每一个客户端连接启用一个线程,这个新的线程将全心全意为这个客户端服务。同时,为了接受客户端连接,服务器还会额外使用一个派发线程。原创 2017-03-25 20:21:37 · 370 阅读 · 0 评论 -
《Java高并发程序设计》学习 --5.9 并行模式之并行算法:矩阵乘法
在矩阵乘法中,第一个矩阵的列数和第二个矩阵的行数必须是相同的。如果需要进行并行计算,一种简单的策略是可以将A矩阵进行水平分割,得到子矩阵A1和A2,B矩阵进行垂直分割,得到子矩阵B1和B2。此时,我们只要分别计算这些子矩阵的乘积,将结果进行拼接,就能得到原始矩阵A和B的乘积。我们使用ForkJoin框架来实现这个并行矩阵相乘的想法。为了方便矩阵计算,我们使用jMatrces开源软件,作为矩阵计原创 2017-03-25 20:15:03 · 1169 阅读 · 1 评论 -
《Java高并发程序设计》学习 --2.8 隐蔽的错误
1)无提示的错误案例int v1 = 1073741827;int v2 = 1431655768;int ave = (v1+v2)/2;System.out.println(ave);上述代码中,视图计算v1和v2的均值。这是一个典型的溢出问题。v1+v2的结果已经导致了int的溢出。2)并发下的ArrayListArrayList是一个线程不安全的容器原创 2017-03-15 22:26:02 · 347 阅读 · 0 评论 -
《Java高并发程序设计》学习 --2.6 线程优先级
下面的代码展示了优先级的作用。高优先级的线程倾向于更快地完成。public class PriorityDemo {public static class HightPriority extends Thread {static int count = 0;@Overridepublic void run() {while(true) {synchronized (Pr原创 2017-03-15 22:02:33 · 349 阅读 · 0 评论 -
《Java高并发程序设计》学习 --2.5 守护线程(Daemon)
只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结束时,守护线程随着JVM一同结束工作。Daemon的作用是为其他线程的运行提供便利服务,守护线程最典型的应用就是 GC (垃圾回收器),它就是一个很称职的守护者。下面看一下守护线程的使用:public class DaemonDemo {public static class D原创 2017-03-15 21:57:19 · 227 阅读 · 0 评论 -
《Java高并发程序设计》学习 --7.11 软件事务内存
在一些函数式编程语言中,支持一种叫做软件事务内存(STM)的技术。这里的事务和数据库中所说的事务非常类似,具有隔离性、原子性和一致性。与数据库事务不同的是,内存事务不具备持久性。在很多场合,某一项功能可能要由多个Actor协作完成。在这种协作事务中,如果一个Actor处理失败,那么根据事务的原子性,其他Actor所进行的操作必须要回滚。下面,看一个简单的案例。假设有一个公司要给它的员工发福原创 2017-04-10 22:55:03 · 985 阅读 · 0 评论 -
《Java高并发程序设计》学习 --7.8 Actor的内置转换状态
一个Actor内部消息处理函数可以拥有多个不同的状态,在特点的状态下,可以对同一消息进行不同的处理,状态之间也可以任意切换。现在模拟一个婴儿Baby,假设婴儿会拥有两种不同的状态,开心或者生气。当带他玩的时候,他总是表现出开心状态,当让他睡觉时,他就会非常生气。在这个简单的场景模拟中,会给这个婴儿Actor发送睡觉和玩两种指令。如果婴儿正在生气,还让他睡觉,他就会说“我已经生气了”,如果你原创 2017-04-09 11:31:13 · 307 阅读 · 0 评论 -
《Java高并发程序设计》学习 --7.7 消息路由
Akka提供了非常灵活的消息发送机制。有时候,会使用一组Actor而不是一个Actor来提供一项服务。这一组Actor中所有的Actor都是对等的,也就是说可以找任何一个Actor来服务。这种情况下,如何才能快速有效地找到合适的Actor?或者说如何调度这些消息,才可以使负载更为均衡地分配在这一组Actor中。为了解决这个问题,Akka使用一个路由器组件(Router)来封装消息的调度。系统提原创 2017-04-08 17:22:40 · 1140 阅读 · 0 评论 -
《Java高并发程序设计》学习 --5.4 高性能的生产者-消费者:无锁的实现
BlockingQueue实现生产者-消费者是一个不错的选择,它很自然地实现了作为生产者和消费者的内存缓冲区。但是,BlockingQueue并不是一个高性能的实现,它完全使用锁和阻塞等待来实现线程间的同步。在高并发场合,它的性能并不是特别优越。 就像我们之前提过的ConcurrentLinkedQueue是一个高性能的队列,但是BlockingQueue只是为了方便数据共享。而Concurren原创 2017-03-20 19:45:45 · 1195 阅读 · 0 评论 -
《Java高并发程序设计》学习 --5.3 并行模式之生产者-消费者模式
生产者-消费者是一个经典的多线程设计模式,它为多线程间的协作提供了良好的解决方案。在生产者-消费者模式中,通常有两类线程,即若干个生产者线程和若干个消费者线程。生产者线程负责提交用户请求,消费者线程负责具体处理生产者提交的任务。生产者和消费者之间则通过共享内存缓冲进行通信。 生产者-消费者模式的核心组件是共享内存缓冲区,它作为生产者消费者间的通信桥梁,避免了两者直接通信,从而将生产者和消费者进原创 2017-03-20 19:33:18 · 518 阅读 · 0 评论 -
《Java高并发程序设计》学习 --5.2 并行模式之不变模式
在并行软件的开发过程中,同步操作似乎是不可避免的,当多线程对同一个对象进行读写操作时,为了保证数据一致性和正确性,有必要对对象进行同步。而同步操作对系统的性能是有相当的损耗的,为了尽可能的取出这些同步操作,提高程序并行能力,可以使用一种不可变对象,依靠对象的不变性 可以确保其在没有同步操作的多线程环境中依然时钟保持内部状态一致性和正确性,这就是不变模式。不变模式天生就是多线程友好的,它的核原创 2017-03-20 19:02:19 · 442 阅读 · 0 评论 -
《Java高并发程序设计》学习 --5.1 探讨单例模式
它是一种对象创建模式,用于产生一个对象的具体实例,确保系统中一个类只有一个实例。这样带来的好处主要有两点: 1. 对于频繁使用的对象,可以省略new操作花费的时间,这样对于那些重量级对象而言,可以节省非常可观的一笔系统开销。2. 由于new操作的次数减少,因而对系统内存的使用频率也会降低,这将减轻GC压力,缩短GC停顿时间。下面给出了一个单例的实现,这个实习生非常简单的,但无疑是一个正原创 2017-03-20 18:57:58 · 252 阅读 · 0 评论 -
《Java高并发程序设计》学习 --4.4 无锁
对于并发控制,锁是一种悲观的策略。它总是假设每一次的临界区操作会产生冲突。如果有多个线程同时需要访问临界区资源,就宁可牺牲性能让线程进行等待,所以说锁会阻塞线程执行。而无锁是一种乐观的策略,它会假设对资源的访问是没有冲突的。无锁的策略使用一种叫做比较交换的技术(CAS Compare And Swap)来鉴别线程冲突,一旦检测到冲突产生,就重试当前操作直到没有冲突为止。1)比较交换(CAS)原创 2017-03-19 22:09:54 · 872 阅读 · 0 评论 -
《Java高并发程序设计》学习 --4.2 Java虚拟机对锁优化所做的努力
1)锁偏向锁偏向是一种针对加锁操作的优化手段。它的核心思想是:如果一个线程获得了锁,那么锁就进入偏向模式。当这个线程再次请求锁时,无须再做任何同步操作。这样就节省了大量有关锁申请的操作,从而提高了程序性能。因此,对于几乎没有锁竞争的场合,偏向锁有比较好的优化效果,因为连续多次极有可能是同一个线程请求相同的锁。而对于锁竞争比较激烈的场合,其效果不佳。因为在竞争激烈的场合,最有可能的情况是每次都是原创 2017-03-18 19:03:00 · 746 阅读 · 0 评论 -
《Java高并发程序设计》学习 --4.3 ThreadLocal
3. ThreadLocal当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。下面看一个简单的示例: private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-M原创 2017-03-18 19:14:48 · 445 阅读 · 0 评论 -
《Java高并发程序设计》学习 --4.1 有助于提高“锁”性能的几点建议
1)减小锁持有时间对于使用锁进行并发控制的应用程序而言,在锁竞争过程中,单个线程对锁的持有时间与系统性能有着直接关系。如果线程持有锁的时间很长,相对地,锁的竞争程度也就越激烈。程序开发过程中,应该尽可能地减少对某个锁的占有时间,以减少线程间互斥的可能。以下面代码为例:public synchronized void syncMethod() {othercode1();mu原创 2017-03-18 12:47:33 · 493 阅读 · 0 评论 -
《Java高并发程序设计》学习 --2.7 线程安全的概念与synchronized
下面的代码演示了一个计数器,两个线程同时对i进行累加操作,各执行10000000次。在很多时候,i的最终值会小于20000000。这就是因为两个线程同时对i进行写入时,其中一个线程的结果会覆盖另一个。public class AccountingVol implements Runnable {static AccountingVol instance = new AccountingVo原创 2017-03-15 22:10:55 · 409 阅读 · 0 评论 -
《Java高并发程序设计》学习 --1.1基础概念
1)同步和异步同步和异步通常用来形容一次方法调用。同步方法调用一旦开始,调用者必须等到方法调用返回后,才能继续后续的行为。异步方法调用更像一个消息传递,一旦开始,方法调用就会立即返回,调用者可以继续后续的操作。2)并发和并行他们都表示两个或者多个任务一起执行。并发偏重于多个任务交替执行,多个任务之间有可能还是串行的。并行的多个任务是真实的同时执行。3)临界区原创 2017-03-15 08:56:17 · 567 阅读 · 0 评论 -
《Java高并发程序设计》学习 --7.3 Akka之Actor的生命周期
一个Actor在actorOf()函数被调用后开始建立,Actor实例创建后,会回调preStart()方法。在这个方法里,我们可以进行一些资源的初始化工作。在Actor的工作过程中,可能会出现一些异常,这种情况下,Actor会需要重启。当Actor被重启时,会回调preRestart()方法(在老的实例上),接着系统会创建一个新的Actor对象实例(但它们都表示同一个Actor)。当新的Acto原创 2017-04-07 08:41:10 · 640 阅读 · 0 评论 -
《Java高并发程序设计》学习 --7.6 消息收件箱(Inbox)
Akka框架准备了一个叫做“收件箱”的组件,使用收件箱,可以很方便地对Actor进行消息发送和接收,大大方便了应用程序与Actor之间的交互。下面定义了当前示例中唯一一个Actor:public class MyWorker extends UntypedActor { private final LoggingAdapter log = Logging.getLogger(getCon原创 2017-04-08 17:18:08 · 814 阅读 · 0 评论 -
《Java高并发程序设计》学习 --7.5 Akka之选择Actor
Akka提供了一个ActorSelection类,用来批量进行消息发送,示意代码如下:for(int i=0; i<WORDER_COUNT; i++) {workers.add(system.actorOf(Props.create(MyWorker.class,i), "worker_" + i));}ActorSelection selection = getContext().原创 2017-04-08 17:15:02 · 1769 阅读 · 0 评论 -
《Java高并发程序设计》学习 --6.5 增强的Future:CompletableFuture
CompletableFuture是Java 8新增的一个超大型工具类。它实现了Future接口,也实现了CompletionStage接口。CompletionStage接口拥有多达40种方法,是为了函数式编程中的流式调用准备的。通过CompletionStage提供的接口,可以在一个执行结果上进行多次流式调用,以此可以得到最终结果。比如,可以在一个CompletionStage上进行如下调用:原创 2017-03-29 22:07:48 · 1083 阅读 · 0 评论 -
《Java高并发程序设计》学习 --6.4 并行流与并行排序
Java 8中,可以在接口不变的情况下,将流改为并行流。这样,就可以很自然地使用多线程进行集合中的数据处理。1)使用并行流过滤数据考虑一个简单的案例,希望可以统计1~1000000内所有的质数的数量。首先,需要做一个质数判断的函数:public class PrimeUtil { public static boolean isPrime(int number) {原创 2017-03-29 21:51:34 · 881 阅读 · 0 评论 -
《Java高并发程序设计》学习 --6.3 一步一步走入函数式编程
首先从简单的例子开始。static int[] arr = {1,2,3,4,5,6,7,8,9,10};public static void main(String[] args) { for(int i:arr) { System.out.println(i); }}上述代码循环遍历了数组内的元素,并且进行了数值的打印。使用Java 8写法如下:原创 2017-03-29 21:41:06 · 553 阅读 · 0 评论