通常情况下,应用程序都是在一个线程中直行操作。但是,当调用一个耗时操作(例如,大批量IO数据或者大量矩阵变换等CPU密集操作)时,用户界面常常会冻结。而使用多线程就可以解决这一问题。
1,提高应用程序的响应速度,这对于开发图形界面的程序尤为重要,当一个操作耗时很长是,整个系统都会等待这个操作,程序就不能及时响应键盘、鼠标、菜单等的操作,而使用多线程技术可以将耗时长的操作置于一个新的线程,从而避免以上问题;
2,使多核CPU系统更加有效。当线程数不大于CPU数目时,操作系统可以调度不同的线程运行与不同的CPU上;
3,改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为独立或者半独立的运行部分,这样有利于代码的理解和维护;
1,多线程程序的行为无法预期,当多次执行上述程序时,每一次的运行结果都可能不同;
2,多线程的执行顺序无法保证,它与操作系统的调度策略和线程优先级等因素有关;
3,多线程的切换可能发生在任何时刻、任何地点;
4,多线程对代码的敏感度高,因此对代码的细微修改都可能产生意想不到的结果。
因此基于以上的特点,为了有效的使用多线程,开发人员必须对其进行控制;
本次主要就根据项目中实际使用的QThreadPool和QRunnable进行简单介绍,大神勿喷;
Qt封装的线程池类是QThreadPool,它的使用需要QRunnable来配合。概括一下使用步骤如下:
1.从QRunnable派生一个类,重写run()函数。把需要子线程干的活放到run函数中。
2.调用QThreadPool的start()开始工作,start的参数就是子类化QRunnable的指针。
QThreadPool pool_; pool_.setMaxThreadCount(4); pool_.start(new Task(high_buffer,low_buffer,height,width,time,this)); //此处的Task为基于public QRunnable创建的类,其中
class Task:public QObject,public QRunnable{
Q_OBJECT
friend class DataAnalyzer;
public:
Task(unsigned short* high_buffer,unsigned short* low_buffer,int height,int width,QTime collect_finish_time,DataAnalyzer* data_analyzer);
void run(){
analyze(high_buffer_,low_buffer_,height_,width_,time_);
}
void analyze(unsigned short* high_buffer,unsigned short* low_buffer,int height,int width,QTime time);
~Task();
private:
unsigned short* high_buffer_;
unsigned short* low_buffer_;
int height_;
int width_;
QTime time_;
};
所以执行为pool_.start()后就把所有的任务扔给了Task即可,具体实现由Task::run()实现。
可以看到新建的任务在子线程中执行了;
线程池在执行完任务后会自动删除任务对象(在start中new出来的CTask),除非你使用setAutoDelete(false)。 QRunnable除了run也就这点本事了。
最后提一点就是Qt为每个QApplication创建了一个线程池对象,通过QThreadPool的静态成员函数globalInstance()可以获得这个对象。不用怀疑拿起来用就是了,出了问题别找我就行了。