最近研究了一些scala并发的知识,总结一下。
一.简介
即时响应性是一项决定任何应用程序成败的关键因素。有两种方式来提高即时响应性:1.多线程,并行运行多个任务。2.有策略的计算,惰性运行任务。
二.惰性求值
1.短路控制,scala不会向前看,所以用到lazy。 注意:多个变量绑定,后续调用,顺序不可预知。
2.惰性集合,创建临时视图,调用的时候立即求值。
3.无限流转换有限流
有限序列
无限流-》Stream
三.并行集合
顺序集合
顺序集合上的方法行为:它们为它们的集合中的每个元素顺序地执行它们的操作。
并行集合
,Scala 都拥有其并行版本。例如,ParArray 是Array 对应的并行版本,同样的,ParHashMap、ParHashSet 和ParVector 分别对应于HashMap、HashSet 和Vector。我们可以使用par()和seq()方法来在顺序集合及其并行版本之间进行相互转换。
四.Actor
简介:
Acotr模式是一种并发模型与另一种模型共享内存完全相反,Actor模型share nothing。 所有线程(或进程)通过消息传递方式进行合作,这些线程(或进程)称为Actor,共享内存更适合单机多核的并发编程。
特点:
- 保证互斥访问的活动对象。
- 一个Actor将只会处理一条消息。Actor模型具有与生俱来的线程安全性。
- 多个Actor并发地运行,同时处理多条消息。
- Actor是异步。
- 不会阻塞调用者。
- 不用显示创建一个线程池,显示调度任务。
- 线程并不和Actor绑定--一个线程池服务于多个Actor。
- java创建共享可变变量,并使用同步原语来提供线程安全性。使用JDK 库很难在短时间内做到正确的并发。
注意:
- 更多依赖无状态Actor,少用有状态Actor。
- 确保Actor之间传递消息是不可变对象(case,String,Int等)。保证我们不会无意间修改共享状态。
- 尽量避免使用ask().双向通信不是一个好主意。“发送并忘记”(!)模型好得多。
示例:
统计字符串的次数。
代码语言:javascript复制import akka.actor._
import scala.collection.mutable
/**
* 接收消息
*/
class MessageActor extends Actor{
val messagesCount: mutable.Map[String, Int] =mutable.Map()
override def receive: Receive = {
case Play(role) =>
val currentCount = messagesCount.getOrElse(role, 0)
messagesCount.update(role, currentCount 1)
println(s"Playing $role")
case ReportCount(role) =>
sender ! messagesCount.getOrElse(role,0)
}
}
case class Play(role: String)
case class ReportCount(role: String)
代码语言:javascript复制import akka.actor._
import akka.util.Timeout
import akka.pattern.Patterns
import scala.concurrent.Await
import scala.concurrent.duration._
/**
* Acotr模式是一种并发模型与另一种模型共享内存完全相反,Actor模型share nothing。
* 所有线程(或进程)通过消息传递方式进行合作,这些线程(或进程)称为Actor,共享内存更适合单机多核的并发编程。
*/
object UseActor extends App{
val system = ActorSystem("sample")
val depp = system.actorOf(Props[MessageActor])
val hanks = system.actorOf(Props[MessageActor])
/**
*tell属于发了就完,什么都不管的类型。
*
*/
depp ! Play("Depp1")
hanks ! Play("Hanks1")
depp ! Play("Depp1")
depp ! Play("Depp2")
println("Sent roles to play ")
/**
* 询问(ask ?)模式,因为发送一条消息并等待响应可能会导致潜在的活锁
* 消息可能永远不会到达,设置超时时间
*/
implicit val timeout: Timeout = Timeout(2.seconds)
val depp1 = Patterns.ask(depp, ReportCount("Depp1"), timeout)
val depp2 = Patterns.ask(depp, ReportCount("Depp2"), timeout)
val hanks1 = Patterns.ask(hanks, ReportCount("Hanks1"), timeout)
val depp1Count = Await.result(depp1, timeout.duration)
val depp2Count = Await.result(depp2, timeout.duration)
val hanks1Count = Await.result(hanks1, timeout.duration)
println(s"Depp played Depp1 $depp1Count time(s)")
println(s"Depp played Depp2 $depp2Count time(s)")
println(s"Hanks played Hanks1 $hanks1Count time(s)")
val terminateFuture = system.terminate()
Await.ready(terminateFuture, Duration.Inf)
}
结果:
Playing Depp1 Playing Hanks1 Sent roles to play Playing Depp1 Playing Depp2 Depp played Depp1 2 time(s) Depp played Depp2 1 time(s) Hanks played Hanks1 1 time(s)
参考《Scala实用指南》