kotlin 基础 coroutines 26

作者: zidea | 来源:发表于2019-04-12 07:43 被阅读13次
kotlin-logo.jpeg

并行(parallel)和并发(concurrency)是两个不同的概念。


parallel-docking-bullet-train.jpg

并行是指多个任务同时都在执行,一般通过多线程、多进程或多台计算机实现。


busy-businesswoman-multitasking-drinking-coffee-talking-on-phone-and-h8hd99.jpg

并发是指至少两个任务都在推进,不一定是并行的,也可以是时间片切分的方式串行。很好例子就是一个人一边和咖啡一边打电话,看似同时进行。但是喝咖啡是无法打电话的。快速地在喝咖啡和打电话之间进行,在倾听对方时候可以喝咖啡,这样就是并发。

public class ZClientD {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,0);
        
    }
}

在 java 8 提供 stream 的Api 方便我们更流畅地操作数组这样集合,这里定义了 transform 方法对集合的元素进行转换。


public class ZClientD {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,0);
        numbers.stream()
                .mapToInt(e -> transform(e))
                .sum();
    }

    private static int transform(Integer e) {
        return e;
    }
}

可以 transform 添加一个延时,然后看一看没有并行处理而是顺序处理的痛苦

    private static int transform(Integer e) {
        sleep(1000);
        return e;
    }

    private static boolean sleep(int ms){

        try {
            Thread.sleep(ms);
            return true;
        } catch (InterruptedException e) {
            e.printStackTrace();
            return false;
        }

    }
}
public class ZClientD {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,0);
        System.out.println(numbers.stream()
                .mapToInt(e -> transform(e))
                .sum());
    }

    private static int transform(Integer e) {
        sleep(1000);
        return e;
    }

    private static boolean sleep(int ms){

        try {
            Thread.sleep(ms);
            return true;
        } catch (InterruptedException e) {
            e.printStackTrace();
            return false;
        }

    }
}

在 kotlin 中,写一个简单函数 process 接收一个参数然后其返回。

fun process(n:Int):Int{
    return n
}

fun main(args: Array<String>) {
    println(process(5))
}

在 process 方法中添加打印线程

fun process(n:Int):Int{
    println("${Thread.currentThread()}")
    return n
}

通过输出可以查看 process 是在主线程中执行的。

Thread[main,5,main]
5

fun process(n:Int):Int{
    println("${Thread.currentThread()}")
    return n
}

当我们使用 launch 来开启协程,然后在协程中执行 process 函数时
fun main(args: Array<String>) {

    GlobalScope.launch{
        println(process(5))
    }

    Thread.sleep(2000)
}

输出线程不再是主线程,而是一个其他线程。

了解 python 的 developer 一定用过 python 提供异步编程,下面代码应该不会陌生,而且在 es6 中也引入 generator 的概念和下面 sequence 有异曲同工。

fun main(args: Array<String>) {

    val sequence = sequence {
        val start = 0
        println("one")
        yield(1)

        println("tow")
        yield(2)

        print("threee")
        yield(3)

        yield("done")
    }

    for (value in sequence){
        println(value)
    }
}

sequence 会返回一个迭代器。迭代器中的值被延迟地计算,可以是无限执行下去的。好处是只有我们在调用序列的下一个值时候一些语句才会被执行,不然程序可以悬挂起来。而且非线程阻塞。

下面内容我们联系实际,可能要看某个分享课程,那么这次查找是有一定顺序就是,先要找到作者然后再根据作者找到其下的课程。下面这里启动两个请求来模拟一下。

fun process(n:Int):Int{
    println("${Thread.currentThread()}")
    return n
}

fun getCouse():String{
    return java.net.URL("http://localhost:4200/").readText()
}

fun getAuthor():String{
    return java.net.URL("http://localhost:4200/author").readText()
}

fun main(args: Array<String>) {

   println(getCouse())
    println(getAuthor())
}
fun main(args: Array<String>) {

    try {
        val author = getAuthor();
        println("you find course of $author ")
        try {
            val course = getCouse()
            println("you find $course of $author ")
        }catch (ex:Exception){
            println("Error")
        }
    }catch (ex:Exception){
        println("Error")
    }

}
suspend fun getCouse():String{
    return java.net.URL("http://localhost:4200/").readText()
}

suspend fun getAuthor():String{
    return java.net.URL("http://localhost:4200/author").readText()
}

fun main(args: Array<String>) {

    GlobalScope.launch {

        try {
            val author = getAuthor();
            println("you find course of $author ")
            try {
                val course = getCouse()
                println("you find $course of $author ")
            }catch (ex:Exception){
                println("Error")
            }
        }catch (ex:Exception){
            println("Error")
        }
    }

    Thread.sleep(2000L)

}
  • suspend 加载 fun 前面表示这个函数就是非阻塞的服务。
  • launch 相当于启动了一个协程。
    暂时从使用方面来看,还是没有 go 语言方便和合理。

服务端的代码是用 go 写的,go 写 web 服务还是很容易。所以许多大公司正在将服务转为 go 编写。滴滴的中台服务就是用 go 开发的。

package main

import(
    "fmt"
    "io"
    "net/http"
)

func index(w http.ResponseWriter, r *http.Request){
    io.WriteString(w, "kotlin coroutines")
}

func getAuthor(w http.ResponseWriter, r *http.Request){
    io.WriteString(w, "zidea")
}

func main(){
    fmt.Println("启动下载服务")
    http.HandleFunc("/", index)
    http.HandleFunc("/author", getAuthor)
    http.ListenAndServe(":4200", nil)
}

本次暂时就到这里,下次继续分享


Java-Vs-Kotlin-–-Which-Should-You-Choose-For-Android-Development.png

相关文章

网友评论

    本文标题:kotlin 基础 coroutines 26

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