DC娱乐网

aardio多任务开发 多线程 线程池

aardio作为一门发展了17年的国产编程语言,自然具有通过多线程并行执行任务的能力。今天一起看看aardio如何执行多线程。

什么是线程

要了解什么是线程,需要先了解什么是进程。进程是一个应用程序运行的最小单位。一个应用程序的进程在运行的时候,至少包括一个线程,通常称之为主线程,比如我们的窗体界面线程,一般就是主线程。一个应用程序除了主进程之外,可能会创建新的线程去执行一些执行起来比较慢的操作。应用程序此时就有了多个线程。

为什么用多线程

根据上面的介绍,使用多线程的目的很明确,提升应用程序处理多任务的并行能力,优化程序性能,让程序运行更流畅更迅速。对于windows窗体程序而言,可以在处理复杂多任务的同时,窗体主界面不卡顿。

创建单个线程

aardio提供了几种创建线程的方式。

  • thread.invoke(线程函数,其他参数)

创建线程但不返回线程句柄,线程句柄已自动关闭。注意线程函数有独立的全局变量环境,线程引用的库应当在线程函数内单独导入。创建后线程会自动运行。

import win.ui;/*DSG{{*/var winform = win.form(text="多线程 —— 入门";right=536;bottom=325)winform.add(button={cls="button";text="启动线程";left=27;top=243;right=279;bottom=305;db=1;dl=1;dr=1;font=LOGFONT(h=-16);z=1};edit={cls="edit";left=27;top=20;right=503;bottom=223;db=1;dl=1;dr=1;dt=1;edge=1;multiline=1;z=2})/*}}*/winform.button.oncommand = function(id,event){		//禁用按钮并显示动画	winform.button.disabledText = {"✶";"✸";"✹";"✺";"✹";"✷"}			//创建工作线程	thread.invoke( 			//线程启动函数		function(winform){						for(i=1;3;1){				sleep(1000); //在界面线程执行 sleep 会卡住								//调用界面控件的成员函数 - 会转发到界面线程执行				winform.edit.print("工作线程正在执行,时间:" + tostring( time() ) ); 			} 						winform.button.disabledText = null;					},winform //窗口对象可作为参数传入工作线程	)}



  • thread.invokeAndWait(线程函数,其他参数)

调用并等待线程函数执行完毕,然后获取此线程函数的返回值。在界面线程等待时界面仍可响应用户操作,线程函数的返回值会返回给调用线程。线程函数拥有独立的全局变量,并应遵守多线程调用规则。值得注意的是,前面介绍的thread.invoke不会返回执行结果。

参数@1指定的线程函数,

参数@1之后的其他可选参数会作为调用线程函数的参数。

import win.ui;/*DSG{{*/var winform = win.form(text="aardio form";right=759;bottom=469)winform.add(button={cls="button";text="读取网页";left=272;top=368;right=624;bottom=440;z=1};edit={cls="edit";text="edit";left=48;top=40;right=720;bottom=336;edge=1;multiline=1;z=2})/*}}*/winform.button.oncommand = function(id,event){    winform.button.disabledText = {"✶";"✸";"✹";"✺";"✹";"✷"}       winform.edit.text = thread.invokeAndWait(        function(winform){            sleep(3000);//暂停模拟一个耗时的操作                        import inet.http;            return inet.http().get("http://www.aardio.com");        },winform    )       winform.button.disabledText = null;}winform.show()win.loopMessage();

线程池

给给个任务创建一个线程,看起来没什么问题。但是,当任务数量很多时,比如成百上千个,创建这么多线程对于操作系统而言会造成很大开销,频繁在多线程切换反而会降低线程执行的性能。这时候,我们就需要创建线程池,管理多线程。

aardio给我们提供了两种线程池方案,thread.works执行相同任务(相同的函数)和thread.manage执行不同任务(不同的函数)。两者都可以指定线程池大小,新添加的任务从线程池里面取线程执行任务。

分别看看案例。thread.manage案例:

import console;import thread.manage;//创建线程管理器manage = thread.manage(3);var thrdFunc = function(name){		import win;	import console;		for(i=1;10;1){ 		console.log( thread.getId(),name )		if( !win.delay(1000) ){ 			//主线程可以用 manage.quitMessage()中断这个循环			console.log("收到退出指令")			return;		}	} 	return 67;}//创建线程,如果线程池已满会自动等待其他线程结束manage.create(thrdFunc,"线程1").onEnd = function(...){	console.log("线程1的回调",...);} //创建线程(忽略线程返回值),如果线程池已满会自动等待其他线程结束manage.createLite(thrdFunc,"线程2").onEnd = function(){	console.log("线程2的回调");}manage.create(thrdFunc,"线程3");/*创建所有线程以后,必须调用 manage.waitClose() 函数等待所有线程执行完成,manage.waitClose() 也会负责触发 onEnd 回调,并自动关闭已结束线程的线程句柄。*/manage.waitClose(); console.pause();

thread.works案例

import console;import thread.works;import time;var testWorksSameTask = function(){	var works = thread.works( 4,    	function(...) {        	import console;        	        	thread.lock("写控制台")        	console.log("线程ID" + thread.getId(),",开始工作,接收到任务指令参数",...)        	thread.unlock("写控制台")        	        	return "返回值,线程ID" + thread.getId();    	}	);		//分派任务	for(i=1;10;1){		works.push("task ->" + i)		}		//退出程序前,等待任务完成并关闭所有线程	works.waitClose(    	function(r){        	console.log( "检查成果", r  )    	}	)}testWorksSameTask()execute("pause")