美颜Java

从原生的Java API创建线程谈起,讲述Scala对「控制结构」抽象的设计与实现.

创建线程

Java8之前,创建一个线程的典型方法如下。

Thread t = new Thread(new Runnable() {
  @Override
  public void run() {
    ...
  }
});

t.start();

使用Java8

使用Java8,可以除去一部分冗余的语法噪声,表达力得到了提升。

Thread t = new Thread(() -> {
  ...
});

t.start();

使用Scala

尝试使用Scala,对Java的接口进行包装处理,可以得到更加人性化的接口。首先定义runnable的控制结构:

def runnable(callback: => Unit) = new Runnable {
  override def run() = callback
}

然后,定义thread的关键字,实现Thread的创建。

def thread(callback: Unit) = new Thread(runnable(callback))

用户API也变得更加简洁,其感觉形如if, while等内置的控制结构,表达力非常强。

thread {
  ...
}

多样化

上例创建的是匿名的线程,如果想创建有名线程,并将其设置为Daemon线程,可以如下设计。

daemon("daemon-service-1") {
  ...
}

可以如下实现:

def daemon(name: String)(callback: => Unit): Thread = {
  val t = new Thread(runnable(callback), name)
  t.setDaemon(true)
  t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler {
    override def uncaughtException(t: Thread, e: Throwable) = 
      error(s"Uncaught exception in ${t.getName}:${e.toString}")
  })
  t
}

t.setUncaughtExceptionHandler的入参有点复杂,可以通过「提取函数」改善表达力。

def daemon(name: String)(callback: => Unit): Thread = {
  val t = new Thread(runnable(callback), name)
  t.setDaemon(true)
  t.setUncaughtExceptionHandler(handler)
  t
}

private def handler = new Thread.UncaughtExceptionHandler {
  override def uncaughtException(t: Thread, e: Throwable) = 
    error(s"Uncaught exception in ${thread.getName}:${e.toString}")
}

接下来,以此类推,可以提取「抽象结构」,改善程序的表现力。

private def handler = onException { (thread, except) =>
  error(s"Uncaught exception in ${thread.getName}:${except.toString}")
}

private def onException(h: (Thread, Throwable) => Unit) =
  new Thread.UncaughtExceptionHandler {
    override def uncaughtException(t: Thread, e: Throwable): Unit = h(t, e)
  }

也就是说,onExceptionrunnable, thread, daemon一样,是对Java接口的修饰或隐藏。

总结

Scala是设计DSL的利器。

借助于柯里化,及其漂亮的大括号语法,使得Scala创建自定义的「控制结构」变得非常容易;同时可以有效地除去冗余的语法噪声,提升代码的可读性。

你可能感兴趣的:(美颜Java)