870920 Menu

TimeSliceThread纤程(时间片线程)详解

TimeSliceThread 继承自Thread,相当于“纤程”,即将一个线程分为不同的时间片,每个时间片执行一个特定的任务。传统的Thread线程,是一个线程执行一个具体的任务,或者说一个任务使用一个线程,而TimeSliceThread则是一个线程执行多个具体的任务,或者说多个具体的任务轮流使用同一个线程来执行各自的操作处理。

如果以上一小节的快递公司为例,则相当于:整个公司只有一辆运输车,多个快递员共享这一辆车,轮流使用以执行各自的任务。为便于理解,对传统线程、线程池和时间片线程(纤程)进行一个对比:(博客发表,表格略)。

表 3 6 JUCE类库中三种线程技术的对比表

时间片线程最大的作用:假设A类的某个成员函数需使用后台线程不间断的重复回调,则让该类继承自TimeSliceClient,在所实现的的纯虚函数useTimeSlice()中调用要回调的成员函数。时间片线程回调的间隔时间(毫秒),即该纯虚函数的返回值。

要使用时间片线程技术,同样需“双类配合”,即:继承自Thread的TimeSliceThread类以及TimeSliceClient类。具体使用3步走:

1、提前写一到多个TimeSliceClient的派生类。该类的对象代表一个需使用后台线程执行某些功能的工作对象,或者说一个工作任务。需继承自TimeSliceClient类,实现其纯虚函数useTimeSlice(),在该函数中执行具体的操作处理。TimeSliceThread类的对象将反复调用此函数,完成具体的功能。TimeSliceClient是一个抽象基类,该类除析构函数外,只有一个纯虚函数:useTimeSlice(),该函数的返回值为重复调用此函数的间隔时间。

2、内容组件类中声明TimeSliceThread对象。该对象的作用:自动开辟一个后台线程,在该线程上调用添加给该对象的每个TimeSliceClient对象的useTimeSlice()函数。
TimeSliceThread thread; // 声明为栈对象

3、添加和移除。内容组件类的构造函数中创建并初始化TimeSliceClient对象,而后TimeSliceThread对象添加所创建的TimeSliceClient对象,启动线程并设置线程优先级。示例:(网站发表,代码略)。

编程时,即可以在内容组件中声明TimeSliceClient和TimeSliceThread对象,也可以在TimeSliceClient派生类中声明TimeSliceThread对象。后一种做法,等于是一个线程执行一个任务,但可以不间断的重复回调,直至TimeSliceThread对象移除TimeSliceClient(即自身this)。

JUCE类库和dRowAudio等优秀的第三方模块中,一大批类继承自TimeSliceClient:
(网站发表,图略)。
图 3 7 TimeSliceClient类谱系图

TimeSliceClient类除虚析构函数外,只有一个纯虚函数:
 int useTimeSlice() 执行实际工作,由TimeSliceThread对象自动回调。

useTimeSlice()的返回值为重复调用此函数的间隔时间。0为无间隔, 不间断的重复调用。负数为不再调用。注意, 返回的间隔时间并不担保精确执行, 系统视实际情况而定。可强制TimeSliceThread对象使用notify()唤醒并重新调用此函数。TimeSliceThread保存并管理添加到本类的TimeSliceClient对象,循环调用每一个,让其执行自己的任务。TimeSliceThread继承自Thread类,内部实现了基类的run()函数。该类无虚函数,非虚析构,这意味着可直接使用此类的对象,而无需派生子类。

重要方法及解释:(网站发布,略)。