并发编程

java并发编程——原子变量介绍

强颜欢笑 提交于 2019-11-30 08:20:30
第一部分:原子变量的前世 我们首先看一个例子:产生一个整数序列,每个值都必须是递增唯一的。我们可以用以下代码实现一个: public class UnsafeSequence{ private int value; public int getNext(){ return value++; } } 上面的代码在单线程环境下运行没有任何问题,但是如果在多线程并发访问的情况下它就会有问题。仔细分析getNext方法实际上它包含了三步操作: 第一步:获得当前value值; 第二步:把当前value值+1; 第三步:返回当前value值。 多个线程并发执行上面方法时,返回的value值极有可能是相同的,这显然违背了我们的初衷,所以这个类不是线程安全的。如下图所示: 我们可以用前面讲到的加锁知识把该类修改成线程安全的,最简单的就是给方法加synchronized; public class SafeSequence{ private int value; public synchronized int getNext(){ return value++; } } 修改完以后这个类现在是线程安全的了。如果有线程正在执行getNext方法,那么其他线程就等待当前线程执行完毕后再执行,这样就保证了整个操作的原子性。当这样做还是会给开发人员带来额外的负担,开发人员不得不去思考在哪些调用是需要共享的

并发编程-Future模式

断了今生、忘了曾经 提交于 2019-11-30 01:13:42
1.Future模式有点类似商品订单。比如在网上进行购物,当看中某一件商品时,就可以提交订单。提交订单完毕在家等候送货上门。卖家根据订单取货、发货,并配送到顾客手中。大部分情况下,卖家处理订单没那么快,可能需要几天时间。而这段时间买家不必再家里等候,可以做其他事情。 将此类推到程序设计中,当某一段程序提交了一个请求,期望得到一个答复。但非常不幸的是,服务程序对这个请求的处理可能非常慢。在传统的单线程环境下,调用函数是同步的,也就是说它必须要等到服务程序返回结果后,才能够进行其他处理。而在Future模式下,调用方式该为异步,而原来等待返回的时间段,在主调用函数中,则可以用于处理其他事物。传统程序的调用流程如下图所示。 图1-1 传统串行程序调用流程 采用Future模式设计程序,调用流程如下。 图1-2 Future模式流程图 表1-3 Future模式的主要参与者 参与者 作用 Main 系统启动,调用Client发出请求你 Client 返回Data对象,立即返回FutureData,并开启ClientThread线程装配RealData Data 返回数据的接口 Future Future数据,构造很快,但是是一个虚拟的数据,需要装配RealData RealData 真实数据,其构造是比较慢的 2.Future模式的代码实现 2.1Main函数的实现

Scala实战:并发-Future和Promise

徘徊边缘 提交于 2019-11-30 01:12:57
并发编程是很困难的,特别是在你没有很好的设计与抽像你的功能层次时。传统的并发解决方案是采用多线程和共享变量,这使得随着代码的增加你很难找到错误根源。 Scala中采用了更好的方案,它不是只基于更低层次的线程的。Scala为用户提供了更高级的抽象: Futures 和 Promises ( Akka 还提供了基于 actor 模式的编程范式,是一种更高层次的并发编程抽象。本文主要讲解 Futures 和 Promises ,这里提供一些进一步学习的参考)。 Future Future 是持有某个值的对象,它完成一些计算并允许在“将来”的某一个时刻获取结果。它也可以是其它计算结果的结果(简单点说就是多个 Future 可以嵌套)。创建一个 Future 最简单的方式就调用它的 apply 方法,它将直接开始一个异步计算,并返回一个 Future 对象,它将包含计算结果。 import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import scala.util.{Success, Failure} def computation(): Int = { 25 + 50 } val theFuture = Future { computation() } 第一行导入了

Java并发编程利用 Condition 实现阻塞队列

六月ゝ 毕业季﹏ 提交于 2019-11-29 23:28:48
什么是阻塞队列 BlockingQueue 队列是一种数据结构,它的特点是先进先出(First In First Out),它有两个基本操作:在队列尾部加入一个元素,从队列头部移除一个元素。队列在多线程应用中,常用于生产-消费场景。 BlockingQueue 是 Java util.concurrent 包下重要的数据结构,BlockingQueue 提供了线程安全的队列访问方式:当阻塞队列进行插入数据时,如果队列已满,线程将会阻塞等待直到队列非满;从阻塞队列取数据时,如果队列已空,线程将会阻塞等待直到队列非空。并发包下很多高级同步类的实现都是基于 BlockingQueue 实现的。 BlockingQueue 具有 4 组不同的方法用于插入、移除以及对队列中的元素进行检查。如果请求的操作不能得到立即执行的话,每个方法的表现也不同。这些方法如下: BlockingQueue 是个接口,你需要使用它的实现之一来使用 BlockingQueue,Java.util.concurrent 包下具有以下 BlockingQueue 接口的实现类: ArrayBlockingQueue:ArrayBlockingQueue 是一个有界的阻塞队列,其内部实现是将对象放到一个数组里。有界也就意味着,它不能够存储无限多数量的元素。它有一个同一时间能够存储元素数量的上限

java并发编程——并发容器和并发工具介绍

喜你入骨 提交于 2019-11-29 19:35:01
java.util.concurrent包下面为我们提供了丰富的类和接口供我们开发出支持高并发、线程安全的程序。下面将从三个方面对这些基础构建类做以介绍和总结。 同步容器类,介绍Vector,HashTable和Collections.SynchronizedXXX(); 并发容器类,介绍ConcurrentHashMap,CopyOnWrite容器以及阻塞队列。 并发工具类,介绍CountLatch,FututeTask,Semaphore和CyclicBarrier。 第一部分:同步容器类 同步容器类包括:Vector和HashTable,这两个类是早期JDK的一部分。此外还包括了JDK1.2之后提供的同步封装器方法Collections.synchronizedXxx()。 同步容器类的问题 我们都知道Vector是线程安全的容器,但当我们对Vector经行复合操作时往往会得到意想之外的结果。比如迭代操作: for(int i=0;i<vector.size();i++){ doSomething(vector.get(i)); } 例如两个线程A和B,A线程对容器进行迭代操作的时候B线程可能对容器进行了删除操作,这样就会导致A线程的迭代操作抛出IndexOutOfBoundsException。而这显然不是我们想得到的结果,所以,为了解决不可靠迭代的问题

JAVA 并发编程- Spring 并发访问的线程安全性问题

那年仲夏 提交于 2019-11-29 00:45:19
首先对于Spring的IOC来说,对象是由Spring来帮我们管理,也就是在Spring启动的时候,在Spring容器中,由Spring给我们创建的,Spring会帮我们维护,一般都是单例的,也就是一个对象。 spring生成对象默认是单例的。通过scope属性可以更改为多例。 第一部分:验证Spring生成对象默认是单例的。 下面我们来一个网上的例子验证一下: <bean id="singleton" class="java.util.Date" scope="singleton"></bean> <bean id="prototype" class="java.util.Date" scope="prototype"></bean> package test; import java.util.Date; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.opensymphony.xwork2.ActionContext; public class TestScope { public static void main(String[] args)