线程的四种状态:
运行、就绪、挂起、结束
sleep()使线程停止一段时间,在sleep时间间隔期期满后,不一定立即恢复执行,原因可能是:
这个时刻其他线程正在运行,除非醒来的线程具有更高优先级或者正在运行的线程因为其他原因而阻塞。
wait()使线程暂停执行,进入等待状态,直到被唤醒或等待时间到。
进入等待(就绪)状态有3种方式:
1)CPU调度给优先级更高的thread,原先的thread进入等待状态
2)阻塞的thread获得资源或者信号,进入等待状态(等待当前thread结束后,便能执行)
3)时间片轮转的情况下,如果时间片到了,也将进入等待状态。
线程的三种模式:
1)单线程
2)单元线程:有多个线程,所有线程都在主应用程序(进程)内存中各自的子段范围内运行。在.Net之前,Visual Basic只能创建单元线程应用程序。
3)自由线程:多个线程同时调用相同的方法和组件,即共享代码段
线程的同步和异步:
例:设计4个线程,其中两个线程每次对j增加1,另外两个线程每次对j减少1。循环100次。
public class ThreadTest1{ private int j; public static void main(String args[]){ //main函数 ThreadTest1 tt = new ThreadTest1(); //得到Main类的实例,才能创建线程(因为线程类是内部类) Inc inc = tt.new Inc(); //得到线程类的实例 Dec dec = tt.new Dec(); for(int i = 0; i < 2; i++){ Thread t = new Tread(inc); //创建线程 t.start(); //开启线程 Thread t = new Tread(dec); t.start(); } } private synchronized void inc(){//j是临界资源,不允许多个线程同时操作j,所以需要同步执行 j++; System.out.println(Thread.currentThread().getName()+"-inc:" + j); } private synchronized void dec(){ j--; System.out.println(Thread.currentThread().getName()+"-dec:" + j); } class Inc implements Runnable{ //线程类 public void run(){ for(int i = 0; i <100; i++){ inc(); } } } class Dec implements Runnable{ public void run(){ for(int i = 0; i <100; i++){ dec(); } } } }
线程间的通信
1. 使用全局变量。
在主线程中定一个全局变量,然后让辅助线程不断地监测该全局变量,当全局变量的值是设定的终止标志值时,停止辅助线程。全局变量必须声明为volatile型变量。
例:
volatile bool bThreadStop = false; AfxBeginThread(recvThreadProc, NULL, THREAD_PRIORITY_NORMAL); UINT RecvThreadProc(LPVOID param) { AfxMessageBox("线程已经启动"); while(!bThreadStop) { //do something } ::AfxMessageBox("线程已经停止"); return 0; }
在需要停止辅助线程时,只要: bThreadStop = true;
2. 使用自定义的消息。
const WM_USERMSG = WM_USER+100; //以下代码为辅助线程 CString strTemp, strIp; strIp = "192.168.0.1"; strTemp.Format("对应IP地址为%s", PCSTR(strIp)); //将字符串指针传回到主线程,如果用::PostMessage会报错 ::SendMessage(hwnd, WM_USERMSG,0,(LPARAM)(PCSTR(strTemp))); LRESULT CScanDlg::WindowProc(UINT message, WPARAM wParam PARAM Param) { CString strTemp; CString strThread; _tagThread *pThread; switch(message) { case WM_SCAN: strTemp = LPCSTR(lParam); MessageBox(strTemp); break; case WM_SCANOVER: pThread = (_tagThread*) wParam; session.Lock(); pThread->nThreadFlag = 3; pThread->pHost = &host[nCurrent]; pThread->strMsg=""; nThreadCount++; break; } return CDialog::WindowProc(message, wParam lParam); }
3.使用事件
一个事件对象可以处于两种状态:信号态和非信号态。
#incude <afxmt.h> //创建事件对象 CEvent g_eventStart; //启动事件 CEvent g_eventStop; //停止事件 //使信号处于信号态 g_event.SetEvent(); UINT ThreadProc(PVOID pParam) { volatile int nTemp,g_nCount; ::WaitForSingleObject(g_eventStart,INFINITE); AfxMessageBox("Thread Start"); for(g_nCount=0;g_nCount<100;g_nCount++) { for(nTemp=0;g_nCount<100;nTemp++) { if(::WaitForSingleObject(g_eventKill,0)==WAIT_OBJECT_0) break; } } return 0; }