美颜Java

作者: 刘光聪 | 来源:发表于2016-08-04 23:31 被阅读548次

    从原生的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

        本文链接:https://www.haomeiwen.com/subject/tflhsttx.html