认识多线程
来源:互联网 发布:安卓手机应用 知乎 编辑:程序博客网 时间:2024/06/03 19:30
线程创建函数介绍
创建线程可以使用系统提供的API函数:CreateThread来完成,该函数将创建一个线程,其函数声明如下:
HANDLE WINAPI CreateThread( __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, __in SIZE_T dwStackSize, __in LPTHREAD_START_ROUTINE lpStartAddress, __in_opt LPVOID lpParameter, __in DWORD dwCreationFlags, __out_opt LPDWORD lpThreadId);下面简单介绍CreateThread函数的每个参数:
lpThreadAttributes
执向LPSECURITY_ATTRIBUTES结构体的指针,使用时我们一般设置为NULL,表示让该线程使用默认的安全性;
dwStackSize
设置线程初始栈的大小,即线程可以将多大的地址空间用于它自己的栈,以字节为单位。默认设置为0,表示使用与调用该函数的线程相同的栈空间大小;
lpStartAddress
指向应用程序定义的LPTHREAD_START_ROUTINE类型的函数的指针,表明新线程的起始地址,由新线程执行;这个函数的声明必须是如下形式,函数名字不做要求:
DWORD WINAPI ThreadProc(LPVOID lpParameter);
lpParameter
新线程的入参,是LPVOID类型,必要时进行相应类型的强制转换;
dwCreationFlags
设置用于控件线程创建的附加标记,若为0表示线程创建后就立即执行,若为CREATE_SUSPENDED表示创建后处于暂停状态;
lpThreadId
这个是个返回值,指向一个变量,用来接收线程的ID,当线程创建成功后,系统就会分配一个线程ID;如果我们不关心线程ID,我们可以设置为NULL;
实例1
新建一个Win32 Console Application类型的工程,并命名为MultiThread.cpp;
代码如下:
// MultiThread.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <windows.h>#include <iostream>using namespace std;//新线程的起始地址DWORD WINAPI Thread1Proc(LPVOID lpParameter){ cout << "Thread1 is ruuning" << endl; return 0;}int _tmain(int argc, _TCHAR* argv[]){HANDLE hThread1 = NULL; //创建新的线程 hThread1 = CreateThread(NULL,0,Thread1Proc,NULL,0,NULL); //无须对新线程设置优先级等操作,关闭之 //良好的编码习惯 CloseHandle(hThread1); cout << "main thread is running" << endl; return 0;}我们执行(Ctrl + F5)这段代码多次后,可以发现其结果有三种情况,导致这情况出现的主要原因是:
操作系统为每一个运行的线程安排一个的CPUT时间---时间片。系统通过一种循环方式为线程提供时间片,线程仅在自己的时间内运行,因为时间片非常的短,所以给我们的感觉就像多个线程是同时运行的,每次执行时系统分配的时间片都是不一致的,所以有时候能执到线程1,有时候在主线程的时间片内,主线程已经执行完毕,主线程退出,线程1没有机会执行;
情况1
情况2
情况3
在我们的main函数返回之前,添加一个Sleep(1000)语句,就能确保执行结果和预期一致,即情况3;
解释如下:
Sleep(1000)表示让主线程睡眠1秒,Sleep的入参是毫秒为单位;由于主线程进入睡眠状态,主线程放弃了执行的权利,线程1得到了运行权利,线程1在1秒内足以执行完成,线程1结束;在1秒后,主线程睡醒,主线程执行完毕,程序退出;
实例2
在这个实例中我们引入一个全局的计数器g_Index,在两个线程中分别打印这个index 和执行的线程标识,其代码如下:
int g_nIndex = 0;const int nMaxCnt = 100;//新线程的起始地址DWORD WINAPI Thread1Proc(LPVOID lpParameter){ while (g_nIndex++ < nMaxCnt) { cout <<"Index = "<< g_nIndex << " "; cout << "Thread1 is ruuning" << endl; } return 0;}int _tmain(int argc, _TCHAR* argv[]){HANDLE hThread1 = NULL; //创建新的线程 hThread1 = CreateThread(NULL,0,Thread1Proc,NULL,0,NULL); //无须对新线程设置优先级等操作,关闭之 //良好的编码习惯 CloseHandle(hThread1); while (g_nIndex++ < nMaxCnt) { cout << "Index = " << g_nIndex << " "; cout << "main thread is running" << endl; } return 0;}运行结果:
我们发现某些行的打印和我们的预期有些不符,例如:“Index = 3Index = 2 main thread is running”,这个就是多线程执行带来的问题,可以使用互斥量来解决,这暂不讨论;
同时我们也可以发现主线程和线程1是交替执行的,这里也体现的了多线程的执行是按照时间片来运行的;
- 认识多线程
- 【多线程】_认识多线程笔记
- Java多线程之认识多线程
- 【多线程】_认识多线程笔记
- Java多线程(一) 认识多线程
- 【JAVA多线程】认识java多线程
- 认识Java多线程
- 多线程的认识
- JAVA:认识多线程
- 从头认识多线程-目录
- 从头认识多线程-目录
- 认识CoreData-多线程
- 认识CoreData—多线程
- 认识CoreData—多线程
- 多线程 并发的认识
- java多线程的认识
- 认识Java多线程
- 线程--认识多线程
- 程序猿小白的2016—不忘初心,继续奋斗
- UML总结
- redis3.0.7源码阅读(十二)redis事件处理
- CentOS64位6.5下部署Zabbix2.2.6监控系统
- 【Android 进阶】EventBus---超级方便的工具
- 认识多线程
- 原生js实现的下拉多选控件,引用只需一个js
- Leetcode——209. Minimum Size Subarray Sum
- python基础语法(4) 字典
- 【个人网站搭建】QQ授权登录
- RecyclerView不调用onCreateViewHolder和onBindViewHolder的解决方法
- 树,森林与二叉树的转换 数据结构期末复习
- Volley的简单应用
- KM算法模板