Basic Of Multi-Threads

来源:互联网 发布:mac os 10.8 iso镜像 编辑:程序博客网 时间:2024/05/20 05:29
1] RHandleBase 类

作为多线程,首先要考虑到的是 RThread 类。RThread 类从 RHandleBase 类继承,所以它首先是一个对象的句柄(a handle of an object),包括了 Close(), Duplicate(), FullName(), Handle(), HandleInfo(), Name(), RHandleBase(), SetHandle(), SetHandleNC() 方法。这个类是一个抽象类,没有自己的实例,通常都是作为其他类的基类使用,例如 RSemaphore, RThread, RProcess, RCriticalSection 等。RTimer 类是从RHandleBase 继承的一个类,可以通过这个类,来说明一些 RHandleBase 的一些问题 。 以下是代码。

#include <e32base.h>
#include <e32cons.h>

// 定义本地数据
LOCAL_D CConsoleBase* console;
LOCAL_C void NewCsoLC();
LOCAL_D TInt err;

//全局函数,被 E32 调用的主函数,
GLDEF_C TInt E32Main()
{
__UHEAP_MARK;
CTrapCleanup* cup=CTrapCleanup::New();
TRAP(err,NewCsoLC());
delete cup;
__UHEAP_MARKEND;
return 0;
}

LOCAL_C void NewCsoLC()
{
__UHEAP_MARK;
_LIT(TITLE,"RHandleBase Demo");
TSize Ts=TSize();
Ts.SetSize(-1,-1);
console=Console::NewL(TITLE,Ts);
CleanupStack::PushL(console);


RTimer RTM;
//创建一个与系统计时器相关联的句柄
RTM.CreateLocal();

//RTM.Close();
//RTM.CreateLocal();


// 获得与当前句柄相关联对象的 handle-number
console->Printf(_L("HandleNum:"));
console->Printf(_L("%d"),RTM.Handle());
console->Printf(_L(" "));

// 设置与当前句柄相关联对象的 handle-number
// 这个值似乎不能乱设,否则将导致系统异常,具体细节不甚清楚
//RTM.SetHandle(180000000);
//RTM.SetHandleNC(18000000000);
//console->Printf(_L("HandleNum:"));
//console->Printf(_L("%d"),RTM.Handle());
//console->Printf(_L(" "));


// 获得句柄全名
console->Printf(_L("FullName:"));
console->Printf(RTM.FullName());
console->Printf(_L(" "));

// 获得句名称
console->Printf(_L("Name:"));
console->Printf(RTM.Name());
console->Printf(_L(" "));

// HandleInfo() 方法需要传入一个 THandleInfo 型的指针
THandleInfo* Hif;
RTM.HandleInfo(Hif);
// 通过这个 Hif 指针可以获取和设置与句柄相关的系统对象的信息。
console->Printf(_L("iNumOpenInProcess:%d "),Hif->iNumOpenInProcess);
console->Printf(_L("iNumOpenInThread:%d "),Hif->iNumOpenInThread);
console->Printf(_L("iNumProcesses:%d "),Hif->iNumProcesses);
console->Printf(_L("iNumThreads:%d "),Hif->iNumThreads);

Hif->iNumOpenInProcess=8;
Hif->iNumOpenInThread=9;
Hif->iNumProcesses=90;
Hif->iNumThreads=4;

console->Printf(_L("iNumOpenInProcess:%d "),Hif->iNumOpenInProcess);
console->Printf(_L("iNumOpenInThread:%d "),Hif->iNumOpenInThread);
console->Printf(_L("iNumProcesses:%d "),Hif->iNumProcesses);
console->Printf(_L("iNumThreads:%d "),Hif->iNumThreads);

//关闭句柄
/*
这个操作对与句柄相关的内核对象也有一定作用。
与句柄相关联的对象似乎是一个引用计数对象,
当外部不再有对该内核对象打开的引用时,Close()方法可以销毁这个内核对象
*/
RTM.Close();
console->Printf(_L("Press to end "));

console->Getch();
CleanupStack::PopAndDestroy();
__UHEAP_MARKEND;
}

[2] RThread 类

在这个类中,需要了解他主要的几个方法。

1.Create()方法:这个方法有四个版本的重载函数,但是基本的参数也就这些:

参 数 描 述 const TDesC& aName 线程的名称 TThreadFunction aFunction 一个指向函数的指针,当线程被恢复时调用该函数,也就是线程最初预定运行的函数。 TInt aStackSize 新线程的 Stack 大小,它不可以为负值,否则函数将发生 USER 109 panic TAny* aPtr 一个指向数据的指针,这些数据是线程函数运行所需要的,如果线程函数不需要参数,则可以把该指针置为NULL TInt aHeapMinSize 新线程 heap 的最小值, 这个值必须不小于在 e32std.h 中定义的 KMinHeapSize,否则函数将发生 USER 110 panic TInt aHeapMaxSize 新线程的 heap 的最大值, 它必须不小于 aHeapMinSize,否则函数将个发生 USER 111 panic TOwnerType aType 它是一个枚举型变量,指明要创建的线程是属于进程还是线程,如果这个值没有被指定,那么将默认 EOwnerProcess,也就是说,新的线程是属于进程的。 RProcess* aProcess 指明当前线程所属的进程 RLibrary* aLibrary 指明线程函数所在的 DLL

2.Resume() 方法:这个方法使创建好的线程处于执行状态。刚刚创建好的线程是处在暂停状态的,Resume() 方法使线程从暂停态转到执行态。

3.Kill() 方法:以指定的原因代码退出指定线程;它与 User::Exit() 的功能类似。

[3] RSemaphore

Semaphore 应该是信号量的意思,这个应该是《操作系统》里的知识吧。信号量(semaphore)是一个内核对象,RSemaphore类提供了对 semaphore的句柄引用。既然它是一个资源类,那么他的使用和操作其他资源类是类似的,在使用前要创建、使用完成后要关闭。

1.Wait() 方法:使信号量减 1。

2.Signal() 方法:使信号量增加 1,如果带参数,则使增加参数所指定的量。

3.Count() 方法:返回当前信号量的值;

以下是两个线程同时使用 两个 TInt 型 :num 和 Tnum 的程序,在这里下载 VC++6 工程文件

#include <e32base.h>
#include <e32cons.h>
#include <E32math.h>

// 定义本地数据
LOCAL_D CConsoleBase* console;
LOCAL_C void ThreadL();
LOCAL_C void NewCsoLC();

LOCAL_C TReal GetRandom();
LOCAL_D TInt err;

const TUint KDefaultHeapSize=0x10000;
//信号量句柄
RSemaphore semaphore;
TInt num;

LOCAL_D RThread T_1,T_2;
LOCAL_D TInt Tnum;

//全局函数,被 E32 调用的主函数,
GLDEF_C TInt E32Main()
{
__UHEAP_MARK;
CTrapCleanup* cup=CTrapCleanup::New();
TRAP(err,NewCsoLC());
delete cup;
__UHEAP_MARKEND;
return 0;
}

LOCAL_C void NewCsoLC()
{
__UHEAP_MARK;
_LIT(TITLE,"RThread Demo");
TSize Ts=TSize();
Ts.SetSize(-1,-1);
console=Console::NewL(TITLE,Ts);
CleanupStack::PushL(console);

console->Printf(_L("Press [C] or [D] "));

TInt i=0;
TKeyCode key;
while(i<1000)
{
key=console->Getch();
//按 Esc 键 退出
__ASSERT_ALWAYS(key!=27,User::Panic(_L("End Thread"),key));
console->Printf(_L("[%d:%c] "),key,key);

// 按 C 键 清除屏幕
if (key==99)
{
console->SetTitle(_L("ClearScreen"));
console->ClearScreen();
}

//press 1 User::After 测试
if (key==49)
{
console->SetTitle(_L("User::After Test"));
for(TInt myi=0;myi<=100;myi++)
{
User::After(10000*(100-myi));
console->Printf(_L("showText:%d "),myi);
}
}

//press 2 User::At 测试
if (key==50)
{
console->SetTitle(_L("User::At Test"));
TTime ttm;
ttm.HomeTime();

TDateTime dtm;
dtm=ttm.DateTime();
console->Printf(_L("%d-%d-%d %d:%d:%d.%d "),dtm.Year,dtm.Month(),dtm.Day(),dtm.Hour(),dtm.Minute(),dtm.Second(),dtm.MicroSecond());
TTimeIntervalSeconds itv=3;
ttm+=(itv);
dtm=ttm.DateTime();
console->Printf(_L("%d-%d-%d %d:%d:%d.%d "),dtm.Year,dtm.Month(),dtm.Day(),dtm.Hour(),dtm.Minute(),dtm.Second(),dtm.MicroSecond());

User::At(ttm);
console->Printf(_L("User::At Test "));
}
// 按 B
if (key==98)
{

TInt64 seed = User::TickCount();
//console->Printf(_L("seed=%d "),seed);
//while(true)
TReal64 a=9;
Math::Pow(a,TReal(2),TReal(32));

console->Printf(_L("%f "),a);

console->Printf(_L("%f "),TReal(Math::Random())/a);

/*
for(TInt ib=0;ib<=10;ib++)
{
User::Beep(1000000,1000000);
}
*/
}
// 按 D
if (key==100)
{

TRAPD(err,ThreadL());
}
}

CleanupStack::PopAndDestroy();
__UHEAP_MARKEND;
}

TInt ThreadFunction(TAny* aAny)
{

TInt *increment = reinterpret_cast<TInt*>(aAny);
for(TInt i=0;i<100;i++)
{
//semaphore.Wait();
Tnum=*increment;
num =100+TInt((*increment)*GetRandom());
User::After(TInt(500000*GetRandom()));

if(i>50)
{
T_1.Kill(0);
semaphore.Signal();
}
if(i>70)
{
T_2.Kill(0);
semaphore.Signal();
}

}
//使信号量的值增加
semaphore.Signal();
Tnum=*increment+10;
return 0;

}

 

LOCAL_C void ThreadL()
{

num = 100;

TInt inc1 = 10, inc2 = -10;

TInt err = T_1.Create(_L("T_1"),ThreadFunction,KDefaultStackSize,KDefaultHeapSize,KDefaultHeapSize,&inc1);
CleanupClosePushL(T_1);
User::LeaveIfError(err);

err = T_2.Create(_L("T_2"),ThreadFunction,KDefaultStackSize,KDefaultHeapSize,KDefaultHeapSize,&inc2);
CleanupClosePushL(T_2);
User::LeaveIfError(err);

//创建一个信号量并初始化
semaphore.CreateLocal(0);


T_1.Resume();
console->Printf(T_1.FullName());
console->Printf(_L(" "));

//
User::After(100000);

T_2.Resume();
console->Printf(T_2.FullName());
console->Printf(_L(" "));


while(semaphore.Count()<2)
{
console->Printf(_L("[%d:%d] "),Tnum,num);
User::After(10);

}

console->Printf(_L("[%d:%d] "),Tnum,num);

T_1.Kill(0);
T_2.Kill(0);

T_1.Close();

// 当两个进程都结束了,那么
// 弹出栈顶的两个元素
CleanupStack::PopAndDestroy(2);

console->Printf(_L("Thread Test: "));

}

// 获得一个O-1的随机数
LOCAL_C TReal GetRandom()
{
TReal64 a=0;
Math::Pow(a,TReal(2),TReal(32));
a=TReal(Math::Random())/a;
return a;

}