QThread实例代表一个线程,我们可以重新实现QThread::run(),要新建一个线程,我们应该先继承QThread并重新实现run()函数。

需要注意的是:

1.必须在创建QThread对象之前创建 QApplication (或QCoreApplication)对象。

2. QCoreApplication::exec() 必须只能从主线程调用,不能从QThread线程调用。

class MyThread : public  QThread

{

Q_OBJECT

public:

MyThread(QObject *parent = NULL);

~MyThread();

protected:

voidrun();

};

void MyThread::run()

{

for( int count = 0; count < 20; count++ )

{

sleep( 1 );

}

qDebug( "finish!");

}

我们可以在另外的函数这样调用:

MyThread thread;

thread.start();

thread.wait();   //必须要加的语句,等待thread结束。

当然我们先开的线程可能是要运行很久,会卡住主线程,使用QeventLoop就可以轻松解决此类问题:

MyThread thread;

thread.start();

QeventLoop;

connect(&thread,SIGNAL(finished ()),&eventLoop,SLOT(quit()));

thread.wait(1);

eventLoop.exec();

接下来我们看QThread的其他属性和函数:

Qthread的优先级属性:Priority指示系统如何调度线程。

Constant

Value

Description

QThread::IdlePriority

0

scheduled only when no other threads are running.

QThread::LowestPriority

1

scheduled less often than LowPriority.

QThread::LowPriority

2

scheduled less often than NormalPriority.

QThread::NormalPriority

3

the default priority of the operating system.

QThread::HighPriority

4

scheduled more often than NormalPriority.

QThread::HighestPriority

5

scheduled more often than HighPriority.

QThread::TimeCriticalPriority

6

scheduled as often as possible.

QThread::InheritPriority

7

use the same priority as the creating thread. This is the default.

0到6的优先级跟windows线程相对应的,就多了一个InheritPriority。

非静态成员函数:

void

exit ( int returnCode = 0 )

该函数告诉线程退出事件循环和返回代码returnCode ;通常返回0意味着成功,非0意味着错误。

需要注意的是,该函数不像C语言的库函数exit一样返回到调用者。除非再次调用QThread::exec(),否则不会再执行任何事件循环。如果QThread::exec()的事件循环没有运行,接着的QThread::exec()将会立即返回。

这两个函数看名字就知道意思:

bool QThread::isFinished ()const

如果线程结束,则返回true,否则返回false。

bool QThread::isRunning ()const

如果线程还在运行则返回true,否则返回false

void QThread::setPriority ( Priority priority )

该函数设置了正在运行的线程的优先级。如果线程没有运行,函数什么也不做,直接返回。跟踪源码发现setPriority 的源码部分如下:

if(!d->running)

{

qWarning("QThread::setPriority:Cannot set priority, thread is not running");

return;

}

如果线程没有运行,函数只输出一个警告便返回了。

需要注意的是:参数不能是InheritPriorty。

case InheritPriority:

default:

qWarning("QThread::setPriority:Argument cannot be InheritPriority");

return;

如果是InheritPriorty,函数也只输出一个警告便返回了。

优先级参数的影响依赖于操作系统的调度策略。特别是,在不支持线程优先级的系统(如linux)优先级参数将被忽略。

void QThread::setStackSize ( uint stackSize )

该函数设置线程堆栈的最大值。

需要注意的是:

1.必须在线程启动之前设置

2. 虽然参数是uint类型,传入负数的话会自动转换。

3.大部分的操作系统都设置了线程堆栈的最大最小值限制。如果超出了限制线程可能运行失败。

验证了一下,当我传-1进去,stackSize值变成了4294967295。Start函数里调用beginthreadex创建新线程。Beginthreadex里调用CreateThread这是大部分用过windows多线程的程序员都了解的。创建失败则输出警告并返回。

d->handle = (Qt::HANDLE)_beginthreadex(NULL, d->stackSize, QThreadPrivate::start,

this, CREATE_SUSPENDED, &(d->id));

if(!d->handle) {

qErrnoWarning(errno, "QThread::start: Failed to create thread");

d->running = false;

d->finished = true;

return;

}

uint QThread::stackSize () const

该函数返回线程堆栈最大值,如果调用setStackSize()设置最大值的话,返回的就是设置的值,否则返回0;

bool QThread::wait ( unsigned long time =ULONG_MAX )

该函数阻塞线程直到满足以下条件之一;

1.      线程已经执行结束。如果线程结束,该函数返回true。如果线程没被启动也会返回true。

2.      Time毫秒时间过去了。如果time 为 ULONG_MAX,该函数永远不会超时。如果超时,函数返回false。

槽函数:

void QThread::quit ()

函数退出事件循环,返回代码为0.与调用exit(0).一样的效果。如果线程没有事件循环则什么也不做。

void QThread::start ( Priority priority =InheritPriority ) [slot]

通过调用开始run(),执行线程。如果线程已经在运行,则什么也不做。

看一下源码:

Start()调用:

d->handle =(Qt::HANDLE) _beginthreadex(NULL, d->stackSize, QThreadPrivate::start, this,CREATE_SUSPENDED, &(d->id));

创建线程。

unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSEQThreadPrivate::start(void *arg)

{

QThread *thr = reinterpret_cast<QThread*>(arg);

QThreadData *data = QThreadData::get2(thr);

。。。。。

。。。。。。          //中间省略,删掉了

emitthr->started();       //发送started信号。

QThread::setTerminationEnabled(true);

thr->run();              //运行我们重新实现的代码。

finish(arg);              //该函数发送finished();信号。

return 0;

}

void QThread::terminate ()

终止线程的运行。线程可能不会理解被终止,这依赖于操作系统的调用策略。在terminate()之后调用QThread::wait()同步终止。

终止线程之后,所有等待线程结束的线程都会被唤醒。

void QThread::terminate()

{

Q_D(QThread);

QMutexLocker locker(&d->mutex);

if(!d->running)

return;

if(!d->terminationEnabled) {

d->terminatePending = true;

return;

}

TerminateThread(d->handle, 0);

d->terminated = true;

QThreadPrivate::finish(this, false);            //finish函数发送了finished()信号。从而会唤醒所有等待的线程。

}

除非真的有必要,不然不要轻易调用该函数。

QThread * QThread::currentThread ()

函数返回当前正在执行的线程。

Qt::HANDLE QThread::currentThreadId ()

注意:

返回当前运行的线程的句柄。该函数返回的句柄只能内部使用,不能在其他任何程序的代码中使用。

在windows系统,该返回值是当前线程的伪句柄。不能用作数值比较,函数返回Win32 函数 getCurrentThreadId()返回的DWORD值。而不是 Win32 函数 getCurrentThread()返回的HANDLE值。

int QThread::idealThreadCount ()

函数返回系统可以运行的理想的线程数。

int QThread::idealThreadCount()

{

SYSTEM_INFO sysinfo;

GetSystemInfo(&sysinfo);

returnsysinfo.dwNumberOfProcessors;    //返回系统中的处理器的数目。

}

void QThread::yieldCurrentThread ()

放弃当前线程转到另外可执行的线程,有系统决定转到哪个线程。

void QThread::sleep ( unsigned long secs )

void QThread::msleep ( unsigned long msecs )

void QThread::usleep ( unsigned long usecs )

这三个函数是让线程进入休眠状态。它们内部都是调用了windows API Sleep。

void QThread::setTerminationEnabled ( bool enabled =true )

设置是否可以终止当前线程。

http://blog.csdn.net/hai200501019/article/details/9535069

Qt线程QThread简析(8个线程等级,在UI线程里可调用thread->wait()等待线程结束,exit()可直接退出线程,setStackSize设置线程堆栈,首次见到Qt::HANDLE,QThreadData和QThreadPrivate)的更多相关文章

  1. C#线程状态简析

    在C# 语言世界中,当我们创建一个新的子线程,该线程状态为unstarted, 子线程开始之后,子线程状态为Running,IsAlive 为true: 线程响应 Thread.Start 并开始运行 ...

  2. nodejs全局对象简析

    Global:全局变量 定时器.控制台输出.事件 模块化相关的一些全局变量 path/url相关的一些全局变量 编码相关的 buffer:缓存(简单介绍) Process:进程(重点解析) 一.Glo ...

  3. Thread类的常用方法_获取线程名称的方法和设置线程名称的方法

    Thread类的常用方法 获取线程的名称: 1.使用Thread类中的方法getName() String getName() 返回该线程的名称 2.可以先获取到当前正在执行的线程,使用线程中的方法g ...

  4. C# 线程池ThreadPool的用法简析

    https://blog.csdn.net/smooth_tailor/article/details/52460566 什么是线程池?为什么要用线程池?怎么用线程池? 1. 什么是线程池? .NET ...

  5. Java多线程简析——Synchronized(同步锁)、Lock以及线程池

    Java多线程 Java中,可运行的程序都是有一个或多个进程组成.进程则是由多个线程组成的.最简单的一个进程,会包括mian线程以及GC线程. 线程的状态 线程状态由以下一张网上图片来说明: 在图中, ...

  6. 并发系列(一)——线程池源码(ThreadPoolExecutor类)简析

    前言 本文主要是结合源码去线程池执行任务的过程,基于JDK 11,整个过程基本与JDK 8相同. 个人水平有限,文中若有表达有误的,欢迎大伙留言指出,谢谢了! 一.线程池简介 1.1 使用线程池的优点 ...

  7. 在不开启事件循环的线程中使用QTimer(QThread::run函数自带事件循环,在构造函数里创建线程,是一种很有意思的线程用法) good

    引入 QTimer是Qt自带的定时器类,QTimer运行时是依赖于事件循环的,简单来说,在一个不开启事件循环(未调用exec() )的线程中,QTimer是无法使用的.通过分析Qt源码可发现,调用QT ...

  8. pyqt4:在线程Qthread中使用定时器Qtimer

    GUI main 部分,主app类中的__init__初始化方法中添加 实例化线程 self.s2_thread=Worker2() 初始化一个定时器 self.log_get=QtCore.QTim ...

  9. Android -- 多媒体播放之MediaPlayer使用内部实现简析

    Android -- MediaPlayer内部实现简析 在之前的博客中,已经介绍了使用MediaPlayer时要注意的内容.如今,这里就通过一个MediaPlayer代码实例,来进一步分析Media ...

随机推荐

  1. JAVA知识的相关积累--用于自己以后查找

    基础: Properties类操作文件,主要是对配置文件的操作.java中的properties文件是一种配置文件,主要用于表达配置信息,文件类型为*.properties,格式为文本文件,文件的内容 ...

  2. gcc代码反汇编查看内存分布[1]: gcc

    # gcc -vgcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5) 重点: 代码中的内存分配, 地址从低到高: 代码段(RO, 保存函数代码) --&g ...

  3. 「OC」block 和 protocol

    一.block   (一)简介 block 是什么?苹果推荐的类型,效率高,在运行中保存代码.用来封装和保存代码,有点像函数,block 可以在任何时候执行.在多线程.异步任务.集合遍历.集合排序.动 ...

  4. NOIP2015前

    时间过得好快...明天就要出发去NOIP了...然后再过半年就要省选了....希望自己能取得好成绩吧... NOIP2015 bless all !

  5. 6月10日-IOS应用-日记本

    嗯,经过这几天的学习,我的第一个IOS应用,日记本算是学习完毕了,下面写一篇日记,记录所学到的知识和需要继续学习的地方. 1,首先是ViewController,必须添加两个协议UITableView ...

  6. 10_9 java笔记

    java中所有的关键字都是小写的注意main虽然被编译器识别,但是它并不是关键字包:(名字小写) 单级包:liyi 多级包:cn.itcast path 和classpath的区别:path环境变量里 ...

  7. H-JATG:NAND_FLASH的参数设置

    JATG:NAND_FLASH     不同的cpu同一款flash:         相同的cpu不同的flash:     相同的cpu不同厂家的的flash:

  8. BZOJ 1965: [Ahoi2005]SHUFFLE 洗牌( 数论 )

    对于第x个数, 下一轮它会到位置p. 当x<=N/2, p = x*2 当x>N/2, p = x*2%(N+1) 所以p = x*2%(N+1) 设一开始的位置为t, 那么t*2M%(N ...

  9. currentStyle和getComputedStyle的兼容写法

    今天学习javascript的时候,教程中介绍了一种简单实现jQuery 中css()方法的写法 <!DOCTYPE html> <html lang="en"& ...

  10. d3.js入门1:安装配置

    D3 是当前流行的数据可视化工具,通过本文能有对 D3 有一个初步认识. 1. D3 是什么 D3 的全称是(Data-Driven Documents),顾名思义可以知道是一个被数据驱动的文档.听名 ...