菏泽网站建设哪好网页制作公司兼职

当前位置: 首页 > news >正文

菏泽网站建设哪好,网页制作公司兼职,管理咨询公司名字,做企业网站注意什么1 Isolate
1.1 什么是Isolate 1.1.1 概念 线程#xff1f;异步#xff1f;隔离#xff1f;到底什么意思#xff1f; Isolate中文意思是隔离#xff0c;从使用角度来说是Dart的线程#xff0c;但是从本质虚拟机的实现角度来讲Isolate是一组封装。 isolate可以理解为dar…1 Isolate  1.1 什么是Isolate 1.1.1 概念 线程异步隔离到底什么意思 Isolate中文意思是隔离从使用角度来说是Dart的线程但是从本质虚拟机的实现角度来讲Isolate是一组封装。 isolate可以理解为dart中的线程但它又不同于线程准确的说应该叫做协程协程最大的优势就是它具有极高的执行效率因为携程中子程序的调用不需要线程的切换所以对于线程数量越大的程序来说协程的优势就越明显。每个isolate都有自己独立的执行线程和事件循环以及内存所以isolate之间不存在锁竞争的问题各个isolate之间通过消息通信。 1.1.2 图例 1.1.3 设计目的 首先说目前由移动端页面包含Android、iOS、Web构建的特性—树形结构构建布局、布局解析抽象、绘制、渲染这一系列的复杂步骤导致必须在同一个线程完成。因为多线程操作页面UI元素会有并发的问题有并发就必须要加锁加锁就会降低执行效率。所以强制在同一线程中操作UI是最好的选择。况且在Flutter中开发者面对的只有一个主Isolate在Isolate中可以通过事件队列来实现异步(网络请求、文件IO)等。 1.1.4 说明 1.为了达到设计目的采取隔离设计去掉锁的应用 2.锁去掉后线程间的信息通信需要建立通信机制来完成参考linux os 底层策略上来讲本质上就是走IO那套体系来完成 1.2 Isolate本质 1.1.1 图例 1.1.2 说明 Dart本身抽象了isolate和thread实际上底层还是使用操作系统的提供的OSThread。 1.3 Isolate组成 1.3.1 Stack用于存放函数调用上下文和调用链路信息。 1.3.2 Heap用于存放对象堆内存回收管理和java类似。 1.3.3 Queue用于存放异步回调分为微事件队列MicroTaskQueue和微任务队列EventQueue。 1.3.4 EventLoop用于处理异步回调。 1.4 Isolate底层逻辑 1.4.1 说明 虽然在内存表现上Isolate内存隔离性像是进程的特点。但是从实现上不可能把Isolate作为一个进程因为进程太重了每新建一个进程内核系统都会为新进程创建独立的虚拟内存保存进程相关的数据结构并且进程切换效率比较低。所以从可行性上来说Isolate的本质应该是一个线程。也就是说Isolate是通过线程实现的。我们使用多个Isolate也就是使用多个线程只不过与传统线程不同的是Isolate之间内存不共享但可以通过通信机制互通。 1.4.2 Isolate如何实现内存隔离 // vm/isolate.cc Isolate*  Isolate::InitIsolate(const char* name_prefix,                               IsolateGroup* isolate_group,                               const Dart_IsolateFlags api_flags,                               bool is_vm_isolate) {   Isolate* result  new Isolate(isolate_group, api_flags);   …        Heap::Init(result,              is_vm_isolate? 0  // New gen size 0; VM isolate should only allocate in old.                  : FLAG_new_gen_semi_max_size * MBInWords,              (is_service_or_kernel_isolate ? kDefaultMaxOldGenHeapSize : FLAG_old_gen_heap_size) *MBInWords);                       …        } 从代码中可以看Isolate的堆内存也被区分为新生代和老年代两块区域Dart虚拟机针对不同的区域执行不同的垃圾回收策略 新生代采用复制清除算法针对频繁创建销毁的页面控件对象可以从内存层面实现快速分配和回收。 老年代采用标记清除和标记整理两种算法来适应不同的内存回收场景尽量保证UI的流畅性。 这里也就解释了Dart中内存分配模型和高效垃圾的回收机制。 1.5 运行图例 1.6 Isolate模式 在dart中编写的代码分为两种类型 1.6.1 同步模式 即正常编写的代码。   BIO模式 1.6.2 异步模式 一些返回类型为Future和Stream的函数。    NIO模式 1.7 Isolate使用案例 1.7.1 常规使用 import dart:isolate; void main(){   print(main begin);   Isolate.spawn((message) {     print(匿名函数线程\(message);   }, inner msg...);   Isolate.spawn(newThread1, hello 1);   Isolate.spawn(newThread2, hello 2);   Isolate.spawn(newThread3, hello 3);   print(main end); } void newThread1(String msg){   print(Thread 1 msg:\)msg); } void newThread2(String msg){   print(Thread 2 msg:\(msg); } void newThread3(String msg){   print(Thread 3 msg:\)msg); } 1.7.2 isolate.spwanUri //当前文件import dart:isolate; ///isolate spawnUri方式 void main() {   print(main begin);   test1();   newThread();   test2();   print(main end); } void test1(){   print(test1…..); } void test2(){   print(test2…..); } ///参数的定义可以随意参数中接收的SendPort是需要通信的发送端口 sendPort void newThread(){   print(新线程…..);   ReceivePort receivePort  ReceivePort();   SendPort sendPort  receivePort.sendPort;   Isolate.spawnUri(Uri(path: ./isolate_spawnUri_task.dart),[msg1,msg2,msg3], sendPort);   //监听   receivePort.listen((message) {     print(主线程接收到来自子线程消息\({message});     switch(message[1]){       case 0:         //子线程正在处理初始化数据...         print(接收到初始化消息);         break;       case 1:         //子线程异步数据正在处理中..         print(接收到处理中状态消息);         break;       case 2:         //子线程数据处理完整         print(接收到任务完成消息);         receivePort.close();        break;     }   }); }//目标文件import dart:isolate; import dart:io; ///isolate spawnUri方式 void main(ListString args,SendPort sendPort) {   print(isolate_spawnUri_task.dart begin);   print(接收到相关参数\)args);   sendPort.send([开始执行异步操作,0]);   sleep(Duration(seconds: 2));   sendPort.send([加载数据中…,1]);   sleep(Duration(seconds: 2));   sendPort.send([异步任务完成,2]);   sleep(Duration(seconds: 2));   print(isolate_spawnUri_task.dart end); } 1.8 Isolate通信 1.8.1 说明 创建Isolate时需要指定一个接收端口ReceivePort的发送端口SendPort调用者可以通过这个发送端口发送数据到其他的Isolate中ReceivePort的listen中这种机制被称为消息传递(message passing) 既然是内存隔离的那么在调用者所在Isolate发送的消息数据是怎么传递到接收者所在的Isolate中的呢也就是说Isolate通信的底层逻辑是什么呢 答案是map_变量map_是一个Hash列表。是在Dart虚拟启动时初始化的所以map_变量是存在于Dart虚拟机所属内存的而这块内是各个Isolate共享的 1.8.2 通信 import dart:isolate;///isolate 通信 - 单向 void main() async{print(main begin);ReceivePort receivePort  ReceivePort();Isolate.spawn(newThread,[你好,receivePort.sendPort]);//方案1通过listen进行监听// receivePort.listen((message) {//   print(listen方式-主线程接收到消息\(message);// });//方案2通过 await关键字与async关键字建立阻塞通道var msg  await receivePort.first;//上面这两种方案上只选选择一种处理//原因这里dart对于数据的等待接收我们可以看做为socket的BIO与NIO//listen方案实际上就是利用selectepoll这种方案在进行循环监听//await 就是read的阻塞式等待print(await方式-主线程接收到消息\)msg);print(main end); }///参数的定义可以随意参数中接收的SendPort是需要通信的发送端口 ///sendPort void newThread(var message){String msg  message[0];SendPort sendPort  message[1];print(通过参数传递的数据1\(msg);//通过传递过来的sendPort给主线程回消息sendPort.send(这个是子线程给主线程回的消息); } 1.8.3 为什么将Isolate设计成隔离的 1、首先说目前由移动端页面包含Android、iOS、Web构建的特性—树形结构构建布局、布局解析抽象、绘制、渲染这一系列的复杂步骤导致必须在同一个线程完成。**因为多线程操作页面UI元素会有并发的问题有并发就必须要加锁加锁就会降低执行效率。所以强制在同一线程中操作UI是最好的选择。**况且在Flutter中开发者面对的只有一个主Isolate在Isolate中可以通过事件队列来实现异步(网络请求、文件IO)等。所以不需要再使用其他线程完成异步。 2、每当有页面交互时必定会引起布局变化而重新绘制这个过程会有频繁的大量的UI控件的创建和销毁这就涉及到了耗时内存分配和回收。而这些较短生命周期的对象是存放在堆内存的新生代的当虚拟机回收新生代内存时是要stop the world的在Android或iOS中各个线程共用一块堆内存当非UI线程频繁申请、释放内存时也会触发垃圾回收所以会间接影响UI线程的运行。 Dart为了解决这个问题就每个Isolate看做线程分配各自的一块堆内存并且独自管理内。这样的策略使得内存的分配和回收变得简单高效并且不受其他Isolate的影响。 1.9 总结 1、Dart中向应用层提供了线程的封装——Isolate。应用层是不能创建线程的只能使用Isolate 2、Isolate与传统的线程不同的是内存隔离 3、Isolate设计成隔离的是出于移动端页面UI构建特性考虑。第一点UI绘制必须在同一线程内完成所以强制同一线程是最好的选择。第二点传统的线程内存共享其他线程频繁的申请释放内存会触发垃圾回收间接影响UI线程运行 2 Dart io  2.1 说明         I/O库使命令行应用程序能够读写文件和浏览目录。读取文件内容有两种选择一次读取全部内容或流式读取。一次读取一个文件需要足够的内存来存储该文件的所有内容。如果文件非常大或者您希望在读取文件时对其进行处理则应使用流如Streaming file contents中所述 2.2 将文件作为文本读取         读取使用UTF-8编码的文本文件时可以使用readAsString()读取整个文件内容。当单独的行很重要时可以使用readAsLines()。在这两种情况下都会返回一个Future对象该对象以一个或多个字符串的形式提供文件的内容。 代码 Futurevoid main() async {var config  File(config.txt);// Put the whole file in a single string.var stringContents  await config.readAsString();print(The file is \){stringContents.length} characters long.);// Put each line of the file into its own string.var lines  await config.readAsLines();print(The file is \({lines.length} lines long.); } 2.3 将文件作为二进制读取         下面的代码将整个文件作为字节读取到整数列表中。对readAsBytes()的调用返回一个Future该函数在可用时提供结果 代码 Futurevoid main() async {var config  File(config.txt);var contents  await config.readAsBytes();print(The file is \){contents.length} bytes long.); }2.4 错误处理         要捕获错误使其不会导致未捕获的异常你可以在Future注册catchError处理程序或者在异步函数中使用try-catch 代码 Futurevoid main() async {   var config  File(config.txt);   try {     var contents  await config.readAsString();     print(contents);   } catch (e) {     print(e);   } } 2.5 用Stream读取文件         使用Stream读取文件一次读取一点。你可以使用Stream API或await for。 代码 import dart:io; import dart:convert;Futurevoid main() async {var config  File(config.txt);StreamListint inputStream  config.openRead();var lines  utf8.decoder.bind(inputStream).transform(const LineSplitter());try {await for (final line in lines) {print(Got \({line.length} characters from stream);}print(file is now closed);} catch (e) {print(e);} }2.6 写文件         您可以使用IOSink将数据写入文件。使用File openWrite()方法获取可以写入的IOSink。默认模式(mode)为FileMode.write完全覆盖文件中的现有数据。 代码 var logFile  File(log.txt); var sink  logFile.openWrite(); sink.write(FILE ACCESSED \){DateTime.now()}\n); await sink.flush(); await sink.close(); 将数据添加到文件末尾可以把可选参数mode指定为FileMode.append var sink  logFile.openWrite(mode: FileMode.append) 添加二进制数据使用add(Listint data)。 2.7 列出目录中的文件         查找目录的所有文件和子目录是一项异步操作。方法返回遇到文件或目录时对象的Stream。 代码 Futurevoid main() async {var dir  Directory(tmp);try {var dirList  dir.list();await for (final FileSystemEntity f in dirList) {if (f is File) {print(Found file \({f.path});} else if (f is Directory) {print(Found dir \){f.path});}}} catch (e) {print(e.toString());} } 2.8 其他常用方法 创建一个文件或目录create()针对文件或目录 删除一个文件或目录delete()针对文件或目录 获取文件的长度length()针对文件 获取对文件的随机访问open()针对文件