实现一个名为PiggybackContext的自定义ExecutionContext类,该类应该可以通过调用execute方法的线程运行Runnable对象
应确保在PiggybackContext对象中运行Runnable对象也能调用execute方法,并能以适当的方式抛出异常
package com.linewell.chapter3
import scala.concurrent.ExecutionContext
import scala.util.{Failure, Success, Try}
/** * 实现一个名为PiggybackContext的自定义ExecutionContext类,该类应该可以通过调用execute方法的线程运行Runnable对象 * 应确保在PiggybackContext对象中运行Runnable对象也能调用execute方法,并能以适当的方式抛出异常 * Created by ctao on 15-12-6. */
class PiggybackContext extends ExecutionContext{
def execute(body:Runnable): Unit = Try(body.run()) match {
case Success(r) => println("success")
case Failure(e) => reportFailure(e)
}
override def reportFailure(cause: Throwable): Unit = println(s"error :${cause.getMessage}")
}
object PiggybackContextTest extends App{
val context = new PiggybackContext
val testError = new Runnable {
override def run(): Unit = {
println("test error")
throw new Exception("error test")
}
}
val testRunnable = new Runnable {
override def run(): Unit = println("test runnable")
}
context.execute(testError)
context.execute(testRunnable)
}
实现一个TreiberStack类,通过该类实现并发堆内存抽象
应在该类中使用先前已经推入该堆栈的指向链接列表节点的院子变量引用,还应该实现无锁算法,并避开ABA问题
package com.linewell.chapter3
import java.util.concurrent.atomic.AtomicReference
import scala.annotation.tailrec
/** * 实现一个TreiberStack类,通过该类实现并发堆内存抽象 * 应在该类中使用先前已经推入该堆栈的指向链接列表节点的院子变量引用,还应该实现无锁算法,并避开ABA问题 * Created by ctao on 15-12-6. */
class TreiberStack[T] {
val buffer = new AtomicReference[List[T]](List.empty[T])
@tailrec
final def push(x: T): Unit = {
val oldList = buffer.get()
if (!buffer.compareAndSet(oldList, x :: oldList)) push(x)
}
@tailrec
final def pop(): T = {
val oldList = buffer.get
if (buffer.compareAndSet(oldList, oldList.tail)) oldList.head
else pop()
}
}
object TreiberStackTest extends App {
val buffer = new TreiberStack[Int]
val t1 = new Thread {
override def run(): Unit = {
for (i <- 1 to 10) {
buffer.push(i)
Thread.sleep(1)
}
}
}
val t2 = new Thread {
override def run(): Unit = {
for (i <- 1 to 10) {
buffer.push(i * 100)
Thread.sleep(1)
}
}
}
t1.start()
t2.start()
t1.join()
t2.join()
for (i <- 1 to 20)
println(s" $i get ${buffer.pop()}")
}
这个暂时还没搞出来
创建一个LazyCell对象并调用apply方法,不允许使用lazy值实现与lazy值相同的语义
package com.linewell.chapter3
/** * Created by ctao on 15-12-6. */
class LazyCell[T](initialization: => T) {
@volatile
var init: Option[T] = None
def apply(): T = init match {
case Some(x) =>
println(s"first init lazy ${System.currentTimeMillis()}")
x
case None => this.synchronized {
init match {
case Some(x) =>
println(s"first init lazy ${System.currentTimeMillis()}")
x
case None =>
println(s"first init lazy ${System.currentTimeMillis()}")
init = Some(initialization)
init.get
}
}
}
println(s"init this class: ${System.currentTimeMillis()}")
}
class LazyCellWithLazy[T](initialization: => T) {
lazy val init: T = {
println(s"first init lazy ${System.currentTimeMillis()}")
initialization
}
println(s"init this class: ${System.currentTimeMillis()}")
}
object LazyCellTest extends App {
def init = {
println("calculation ...")
Thread.sleep(1000)
s"result (calculate by ${Thread.currentThread().getName})"
}
val lazyTest = new LazyCell[String](init)
Thread sleep 1000
println(lazyTest.apply())
val lazyWithLazyTest = new LazyCellWithLazy[String](init)
Thread sleep 1000
println(lazyWithLazyTest.init)
}
使用和5LazyCell类相同的接口和语义,实现一个PureLazyCell类,应在不收参数初始化操作影响的前提下,是PureLazyCell类能多次求值
package com.linewell.chapter3
import java.util.concurrent.atomic.AtomicReference
import scala.annotation.tailrec
import scala.util.Random
/** * Created by ctao on 15-12-6. */
object PureLazyCellTest extends App {
class PureLazyCell[T](initialization: => T) {
val value = new AtomicReference[Option[T]](None)
@tailrec
final def apply(): T = value.get() match {
case None => if (value.compareAndSet(None, Some(initialization))) initialization else apply()
case Some(v) => v
}
}
def initialization = {
val init = Random.nextInt()
println(s"${Thread.currentThread().getName}:$init:${System.currentTimeMillis()}")
s"${Thread.currentThread().getName}:$init"
}
val p = new PureLazyCell[String](initialization)
import com.linewell.chapter2.thread
Range(1, 10).map { i =>
thread{ Thread sleep 1000;println(s"p:${p.apply()}")}
}.foreach(_.join)
}
实现一个SyncConcurrentMap类,通过扩展scala.collection.concurrent.Map接口,使用synchronizd防止并发操作
package com.linewell.chapter3
import scala.collection.concurrent.Map
/** * Created by ctao on 15-12-6. */
class SyncConcurrentMap[A, B] extends Map[A, B] {
private val myMap = collection.mutable.Map.empty[A, B]
override def putIfAbsent(k: A, v: B): Option[B] = myMap.synchronized {
myMap.get(k) match {
case None => myMap.put(k, v)
case optV@Some(_) => optV
}
}
override def replace(k: A, oldValue: B, newValue: B): Boolean = myMap.synchronized {
myMap.get(k) match {
case Some(v) if (oldValue != null && v.equals(oldValue)) || (v == null && oldValue == null) => myMap.put(k, newValue)
true
case _ => false
}
}
override def replace(k: A, v: B): Option[B] = myMap.synchronized {
myMap.get(k) match {
case old@Some(oldValue) => myMap.put(k, v)
old
case None => None
}
}
override def remove(k: A, v: B): Boolean = myMap.synchronized {
myMap.get(k) match {
case Some(value) if (value != null && value.equals(v)) || (value == null && v == null) => myMap.remove(k)
true
case _ => false
}
}
override def -=(key: A): SyncConcurrentMap.this.type = myMap.synchronized {
myMap.remove(key)
this
}
override def +=(kv: (A, B)): SyncConcurrentMap.this.type = myMap.synchronized {
myMap.put(kv._1, kv._2)
this
}
override def get(key: A): Option[B] = myMap.synchronized {
myMap.get(key)
}
override def iterator: Iterator[(A, B)] = myMap.synchronized {
myMap.iterator
}
}
object SyncConcurrentMapTest extends App{
val m = new SyncConcurrentMap[Int, String]()
import com.linewell.chapter2.thread
val t = (1 to 100).map((i) => thread {
(1 to 100).foreach {
(k) => {
val v = s"${Thread.currentThread().getName}"
m.put(k, v)
println(s"-> ($k,$v)")
}
}
})
Thread.sleep(100)
for ((k, v) <- m) {
println(s"<- ($k,$v)")
}
t.foreach(_.join)
}
package com.linewell
/** * Created by ctao on 15-11-29. */
package object chapter2 {
def thread(body: =>Unit) :Thread = {
val t = new Thread{
override def run() = body
}
t.start()
t
}
}
package com.linewell.other
import java.io.{FileNotFoundException, InputStream}
import java.net.{MalformedURLException, URL}
import scala.io.Source
import scala.util.{Failure, Success, Try}
/** * Created by ctao on 15-12-6. */
object TryDemo extends App {
def parseURL(url: String) = Try(new URL(url))
parseURL("http://www.baidu.com") match {
case Success(r) => println(s"success ${r.getProtocol}")
case Failure(e) => println(s"fail ${e.getMessage}")
}
val successContent = parseURL("http://www.baidu.com").map(_.getContent)
println(successContent)
val failContent = parseURL("baidu").map(_.getContent)
println(failContent)
// def inputStreamForURL(url: String): Try[Try[Try[InputStream]]] = parseURL(url).map { u =>
// Try(u.openConnection()).map(conn => Try(conn.getInputStream))
// }
def inputStreamForURL(url: String): Try[InputStream] = parseURL(url).flatMap { url =>
Try(url.openConnection()).flatMap(conn => Try(conn.getInputStream))
}
def parseHttpURL(url: String) = parseURL(url).filter(_.getProtocol == "http")
println(parseHttpURL("http://apache.openmirror.de")) // results in a Success[URL]
println(parseHttpURL("ftp://mirror.netcologne.de/apache.org") )// results in a Failure[URL]
parseHttpURL("http://danielwestheide.com").foreach(println)
def getURLContent(url: String): Try[Iterator[String]] =
for {
url <- parseURL(url)
source = Source.fromURL(url)
} yield source.getLines()
getURLContent("http://danielwestheide.com/foobar") match {
case Success(lines) => lines.foreach(println)
case Failure(ex) => println(s"Problem rendering URL content: ${ex.getMessage}")
}
val content = getURLContent("http://www.baidu.com") recover {
case e: FileNotFoundException => Iterator("Requested page does not exist")
case e: MalformedURLException => Iterator("Please make sure to enter a valid URL")
case _ => Iterator("An unexpected error has occurred. We are so sorry!")
}
content.get.foreach(println)
}