一、介绍
Kilim是一个专为Java设计的轻量级协程框架,它通过字节码操纵技术实现了轻量级的协程,为Java开发者提供了更为灵活的并发编程选项。以下是关于Kilim协程框架的解析与应用:
1、Kilim协程框架解析
- 协程(Coroutine)概念:协程是一种用户态的轻量级线程,它的执行可以在任何时候被挂起和恢复,由程序员控制其执行流程。协程的优势在于其轻量级和高效的上下文切换,可以大大降低并发编程的复杂度。
- Kilim框架特性:
- 提供了超轻量级的线程和工具,支持快速、安全、零复制的消息传递。
- 核心在于Mailbox跨线程共享内存,没有锁或同步,Mailbox支持多生产者,单消费者队列。
- Actor协程场景存在大量的处理线程,都消耗在等待后端的处理,做异步化才有意义。
- 类似于消息机制的方式,在守护线程和外部线程之间有一个队列(俗称信箱),外部线程只要把请求放入,守护线程就读取进行处理。
- 核心组件:
- 任务载体(Task):Task对象是Kilim中核心的结构,所有业务的逻辑代码都是在Task中执行。
- 任务调度器(Scheduler):Scheduler是Kilim框架中核心的任务调度器,负责管理任务的工作者线程WorkerThread,以及一个基本的FIFO队列,维护着Task任务列表。Scheduler负责分派Task给指定的工作者线程WorkerThread执行。
- 任务上下文(Filber)
2、Kilim协程框架应用
- 网络通信:Kilim的协程模型非常适合处理大量的并发网络请求,例如Web服务器、代理服务器等。通过将网络请求封装为Task,使用Scheduler进行调度,可以实现高效的网络通信。
- 高性能计算:对于需要大量计算资源的场景,如科学计算、大数据分析等,Kilim协程框架可以提供高效的并发处理能力。通过将计算任务拆分为多个Task,利用多核CPU并行处理,可以显著提高计算性能。
- 异步编程:Kilim协程框架支持异步编程模型,使得开发者可以以更加直观和顺序的方式编写异步代码。通过将异步操作封装为Task,可以方便地实现异步回调、错误处理等功能。
- 游戏开发:在游戏开发中,需要处理大量的并发事件和实时交互。Kilim协程框架可以提供高效的并发处理能力,使得开发者可以更加灵活地控制游戏逻辑的执行流程。
总之,Kilim协程框架为Java开发者提供了一种轻量级、高效的并发编程解决方案。通过利用协程的轻量级和高效的上下文切换特性,可以大大降低并发编程的复杂度,提高程序的性能和可维护性。
二、协程与线程性能对比
1、生产者和消费者案例
(1)Java多线程是吸纳
package chatpter11;
import java.util.ArrayList;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicLong;
/**
* 创建了1000个生成者和1000个消费者,每个生产者生产10个产品,1000个消费者同时消费产品
**/
public class TestThread {
LinkedBlockingQueue<Integer> warehouse = new LinkedBlockingQueue<>(10);
AtomicLong producerCount = new AtomicLong(0); //生产次数计数
AtomicLong consumerCount = new AtomicLong(0); //消费次数计数
private static final Integer FULL = 10; //最大生产数量
public static void main(String[] args) {
TestThread test = new TestThread();
long startTime = System.currentTimeMillis(); //开始时间
ArrayList<Thread> list = new ArrayList<>();
for (int i = 0; i < 1000; i++) { //创建1000个生产者线程
Thread thread = new Thread(test.new Producer());
thread.start();
list.add(thread);
}
for (int i = 0; i < 1000; i++) { //创建1000个消费者线程
Thread thread = new Thread(test.new Consumer());
thread.start();
list.add(thread);
}
try {
for (Thread thread : list) {
//等待所有线程执行完
thread.join();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("多线程执行时长: " + (System.currentTimeMillis() - startTime));
}
// 生产者(生产10个商品)
class Producer implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
warehouse.put(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
producerCount.incrementAndGet();
System.out.println(Thread.currentThread().getName() + "生产者生产,目前总调用" + producerCount);
}
}
}
//消费者(消费10个商品)
class Consumer implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
warehouse.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
consumerCount.incrementAndGet();
System.out.println(Thread.currentThread().getName() + "消费者消费,目前总调用" + consumerCount);
}
}
}
}
多线程执行时长: 1447
(2)kilim协程框架实现
package chatpter11;
import kilim.Mailbox;
import kilim.Task;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
* 创建了1000个生成者和1000个消费者,每个生产者生产10个产品,1000个消费者同时消费产品
* kilim协程实现
**/
public class TestKilim {
public static Map<Integer, Mailbox> mailMap = new HashMap<>();
public static void main(String[] args) {
//判断是否引入kilim
if (kilim.tools.Kilim.trampoline(false, args)) {
return;
}
Properties properties = new Properties();
//设置4个工作线程
properties.setProperty("kilim Scheduler.numThreads", "4");
System.setProperties(properties);
long startTime = System.currentTimeMillis();
//todo 创建1000个生产者任务
for (int i = 0; i < 1000; i++) {
//相当于仓库,最大容量10
Mailbox<Integer> mb = new Mailbox<>(1, 10);
new ProducerTask(i, mb).start();
//生产者把mailbox写入
mailMap.put(i,mb);
}
for(int i = 0; i < 1000; i++) {
//消费者把mailbox获取
new ConsumerTask(mailMap.get(i)).start();
}
//开始运行
Task.idledown();
long endTime = System.currentTimeMillis();
System.out.println("kilim总计花费时长: " + (endTime - startTime));
}
}
consumer:
package chatpter11;
import kilim.Mailbox;
import kilim.Pausable;
import kilim.Task;
import java.util.concurrent.atomic.AtomicLong;
public class ConsumerTask extends Task<Object> {
final static AtomicLong consumerCount = new AtomicLong();
Mailbox<Integer> mb = null;
public ConsumerTask(Mailbox<Integer> mb) {
this.mb = mb;
}
public void execute() throws Pausable {
Integer c = null;
for (int i = 0; i < 10; i++) {
c = mb.get(); //获取消息,阻塞协程线程(在mailbox为空时,消费者get会阻塞)
consumerCount.incrementAndGet();
System.out.println(Thread.currentThread().getName() + ":消费者,目前总调用" + consumerCount);
}
}
}
producer:
package chatpter11;
import kilim.Mailbox;
import kilim.Pausable;
import kilim.Task;
import java.util.concurrent.atomic.AtomicLong;
public class ProducerTask extends Task<Object> {
final static AtomicLong producerCount = new AtomicLong();
Integer count = null;
Mailbox<Integer> mb = null;
public ProducerTask(Integer count, Mailbox<Integer> mb) {
this.count = count;
this.mb = mb;
}
//相当于线程的run方法
public void execute() throws Pausable {
for(int i = 0; i < 10; i++) {
mb.put(count); //malbox满了,生产者put会阻塞
producerCount.incrementAndGet();
System.out.println(Thread.currentThread().getName() + ":生产者,目前总调用" + producerCount);
count++;
}
}
}
运行结果:
kilim总计花费时长: 670