第6章:并发
一、导读
1.1 本章学习目标
第6章讲解 Scala 的并发编程:Future、Promise、Actor 模型。
本章核心学习目标:
- 掌握 Future:异步计算
- 理解 Promise:手动完成 Future
- 了解 Actor 模型:Akka 基础
1.2 为什么本章如此重要
并发是现代编程的核心挑战。Scala 提供了多种并发模型,Future 是最常用的。
1.3 核心问题引导
Future 如何避免回调地狱?
Promise 和 Future 的关系是什么?
Actor 模型比线程有什么优势?
二、核心概念详解
6.1 Future
scala
import scala.concurrent._
import scala.concurrent.duration._
import ExecutionContext.Implicits.global
// 创建 Future
val future = Future {
Thread.sleep(1000)
42
}
// 回调
future.onComplete {
case Success(value) => println(s"Got: $value")
case Failure(ex) => println(s"Error: ${ex.getMessage}")
}
// 转换
val doubled = future.map(_ * 2)
val filtered = future.filter(_ > 10)
val recovered = future.recover { case _ => 0 }
// 组合
val f1 = Future(1)
val f2 = Future(2)
// for 推导式
val result = for {
a <- f1
b <- f2
} yield a + b
// 或 zip
val zipped = f1.zip(f2).map { case (a, b) => a + b }
// 等待结果 (测试用)
val value = Await.result(future, 5.seconds)6.2 Promise
scala
// Promise: 手动完成 Future
val promise = Promise[Int]()
val future = promise.future
// 在另一个线程中完成
Future {
Thread.sleep(1000)
promise.success(42)
}
// 完成方式
// promise.success(value)
// promise.failure(exception)
// promise.trySuccess(value) // 不抛异常
// promise.tryFailure(ex)6.3 Actor 模型 (Akka)
scala
import akka.actor._
// 定义消息
case class Greet(name: String)
case class Reply(message: String)
// 定义 Actor
class Greeter extends Actor {
def receive = {
case Greet(name) =>
println(s"Hello, $name!")
sender() ! Reply(s"Hello, $name!")
case msg =>
println(s"Unknown message: $msg")
}
}
// 创建和使用
val system = ActorSystem("MySystem")
val greeter = system.actorOf(Props[Greeter], "greeter")
greeter ! Greet("Alice")
greeter ! Greet("Bob")
// system.terminate()三、实战案例
3.1 案例一:并发 HTTP 请求
scala
import scala.concurrent._
import scala.concurrent.duration._
import ExecutionContext.Implicits.global
def fetchUrl(url: String): Future[String] = Future {
// 模拟 HTTP 请求
Thread.sleep(scala.util.Random.nextInt(1000))
s"Response from $url"
}
val urls = List(
"https://api1.example.com",
"https://api2.example.com",
"https://api3.example.com"
)
// 并发执行所有请求
val futures = urls.map(fetchUrl)
val allResults = Future.sequence(futures)
// 等待所有完成
val results = Await.result(allResults, 10.seconds)
results.foreach(println)
// 带超时的版本
val withTimeout = Future.firstCompletedOf(
futures :+ Future.failed(new TimeoutException("Timeout"))
)四、本章小结
Future 表示异步计算的结果
Promise 手动完成 Future
Actor 模型提供消息传递的并发范式
五、思考与练习
Future 的 ExecutionContext 是什么?
Actor 模型如何避免死锁?