Dart Isolate 多线程

476 阅读2分钟

Isolate是dart中的线程

Dart中的线程是以隔离(Isolate)的方式存在的
每个Isolate都有自己独立的,私有内存块(多个线程不共享内存)
没有共享内存,就不需要竞争资源,就不需要锁(不必担心死锁问题)

所有的Dart代码,都运行在Isolate中

Isolate提供了Dart | Flutter的运行环境
微任务队列,事件队列,事件轮询(EventLoop)都在Isolate中进行

多线程经常用来解决耗时较长的异步任务

截屏2022-05-08 下午4.46.08.png

Isolate多线程创建

   // Isolate类用来管理线程(创建、暂停、杀死Isolate线程)
   
   // 创建线程(可以调用当前文件中的函数)
   Isolate.spawn()
   
   // 创建线程(可以调用另外一个文件中的函数)
   Isolate.spawnUri()
   
   // 暂停线程
   Isolate.pause()
   
   // 杀死线程
   Isolate.kill()

示例

import 'dart:isolate';

void main(List<String> args) {

    multiThread();
}

void multiThread() {

    print('multiThread start');

    print('当前线程:' + Isolate.current.debugName);

    Isolate.spawn(newThread, 'hello');
    
    print('multiThread end');

}

void newThread(String message) {

    print('当前线程:' + Isolate.current.debugName);

    print(message);
}

Isolate多线程之间通信机制

Isolate多线程之间,通信的唯一方式是port
ReveivePort类:初始化接收端口,创建发送端口,接收消息,监听消息,关闭端口
SendPort类:将消息发送给ReceivePort
通信方式:单向通信、双向通信

Isolate之间通讯,总结就是,通过SendPort作为中介传递给要通讯的线程,然后通过ReveivePort接收或者监听消息,双向通讯其实就是简历在单向通讯的基础上,当单向通讯已经建立了,就可以传送自己线程的SendPort,然后用ReveivePort监听SendPort发送的消息

单向通信

截屏2022-05-08 下午6.20.25.png

示例

import 'dart:isolate';

void main(List<String> args) {
    multiThread();
}

void multiThread() async {
    print('multiThread start');
    print('当前线程:' + Isolate.current.debugName);

    // 接收端口
    ReceivePort r1 = ReceivePort();

    // 发送端口
    SendPort p1 = r1.sendPort;
    
    // 创建新线程  
    Isolate.spawn(newThread, p1);

    // 接收新线程发送过来的消息
    // var msg = await r1.first;
    // print('来自新线程的消息:' + msg.toString());

    r1.listen((message) {
         print('来自新线程的消息:' + message.toString());
         
        // 如果不关闭的话主线程会被阻塞
        r1.close();
    });

    print('multiThread end');
}

void newThread(SendPort p1) {
    print('当前线程:' + Isolate.current.debugName);

    // 发送消息给 main 线程
    p1.send('abc');
}

双向通信

截屏2022-05-08 下午6.23.06.png

示例

import 'dart:isolate';

void main(List<String> args) {
    multiThread();
}

void multiThread() async {
    print('multiThread start');
    print('当前线程:' + Isolate.current.debugName);

    // 接收端口
    ReceivePort r1 = ReceivePort();

    // 发送端口
    SendPort p1 = r1.sendPort;

    Isolate.spawn(newThread, p1);

    // 接收新线程发送过来的消息
    // r1.listen((message) {

    // print('来自新线程的消息:' + message.toString());

    // // 如果不关闭的话主线程会被阻塞

    // r1.close();

    // });

    SendPort p2 = await r1.first;

    p2.send('来自主线程的消息');

    print('multiThread end');

}

void newThread(SendPort p1) {
    print('当前线程:' + Isolate.current.debugName);

    ReceivePort r2 = ReceivePort();

    SendPort p2 = r2.sendPort;

    // 发送消息给 main 线程

    p1.send(p2);

    r2.listen((message) {
        print(message);
    });
}

Isolate.spawnUri()创建线程 使用方法

主线程文件中

import 'dart:isolate';
void main(List<String> args) {
    start();
    // 执行耗时的任务
    newIsolate();
    init();
}

void start() {
    print('应用启动:' + DateTime.now().microsecondsSinceEpoch.toString());
}

void newIsolate() async {
    print('新线程创建');

    ReceivePort r = ReceivePort();

    SendPort p = r.sendPort;

    // 创建新线程
    Isolate childIsolate = await Isolate.spawnUri(
        Uri(path: 'childIsolate.dart'),
        ['data1', 'data2', 'data3'],
        p,
    );

    // 监听消息
    r.listen((message) {
        print('主线程接收到数据:${message[0]}');
        if (message[1] == 1) {
            // 异步任务正在处理
        } else if (message[1] == 2) {
            // 取消监听
            r.close();
            // 杀死新线程,释放资源
            childIsolate.kill();
            print('子线程已经释放');
        }

    });
}

init() {}

子线程文件中

import 'dart:io';
import 'dart:isolate';
void main(List<String> args, SendPort mainSendPort) {

    print('新线程接受到的参数:$args');

    mainSendPort.send(['开始执行异步', 0]);

    sleep(Duration(seconds: 1));

    mainSendPort.send(['加载中', 1]);

    sleep(Duration(seconds: 1));

    mainSendPort.send(['异步任务完成', 2]);

}

参考