并行(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
网友评论