이번 강의에서는 멀티스레드에 대한 복습을 진행하였다.
멀티스레드는 멀티코어 프로세서 덕분에 유용하지만, 스레드의 동작을 예측하기 어렵다.
스레드 관리에는 여러 메서드가 있지만, 'stop', 'suspend', 'resume' 와 같은 메서드는 위험하며 잘 사용하지 않는다.
대신 'synchronize' 메서드를 사용하여 스레드 동기화를 추구할 수 있다.
이 메서드는 특정 객체에 대한 동시 접근을 제어한다.
공부한 내용은 주석 내에도 있다.
package part1recap
import scala.concurrent.Future
import scala.util.{Failure, Success}
object MultithreadingRecap extends App {
// creating threads on the JVM
val aThread = new Thread(() => println("I'm running in parallel"))
aThread.start()
aThread.join()
val threadHello = new Thread(() => (1 to 1000).foreach(_ => println("hello")))
val threadGoodbye = new Thread(() => (1 to 1000).foreach(_ => println("goodbye")))
threadHello.start()
threadGoodbye.start()
// different runs produce different results!
// @volatile : 휘발성있는
class BankAccount(@volatile private var amount: Int) {
override def toString: String = "" + amount
def withdraw(money: Int) = this.amount -= money
// 동기화된 표현식에서는 두 스레드가 평가될 수 없기 때문에 스레드로부터 안전함
def safeWithdraw(money: Int) = this.synchronized {
this.amount -= money
}
}
/*
은행계좌 예시
BA (10000)
T1 -> withdraw 1000
T2 -> withdraw 2000
T1 -> this.amount = this.amount - .... // PREEMPTED by the OS
T2 -> this.amount = this.amount - 2000 = 8000
T1 -> -1000 = 9000
=> result = 9000
this.amount = this.amount - 1000 is NOT ATOMIC Atiomic : 원자성, 두 개의 스레드가 동시에 하나를 실행할 수 없음
*/
// inter-thread communication on the JVM
// wait - notify mechanism
// Scala Futures
// futures : future 유형의 동반 객체에서 적용 메소드를 호출하는 것
import scala.concurrent.ExecutionContext.Implicits.global // 전역 실행 컨텍스트 가져옴
val future = Future {
// long computation - on a different thread
42
}
// callbacks
future.onComplete {
case Success(42) => println("I found the meaning of life")
case Failure(_) => println("something happened with the meaning of life!")
}
val aProcessedFuture = future.map(_ + 1) // Future with 43
val aFlatFuture = future.flatMap { value =>
Future(value + 2)
} // Future with 44
val filteredFuture = future.filter(_ % 2 == 0) // NoSuchElementException
// for comprehensions
val aNonsenseFuture = for {
meaningOfLife <- future
filteredMeaning <- filteredFuture
} yield meaningOfLife + filteredMeaning
// andThen, recover/recoverWith
// Promises
}