C++Builder 多线程简介以及实现

多线程编程是提高系统资源利用率的一种常见方式。它占用的资源更小,启动更快,还可以实现在后台运行一些需时较长的操作。

一、初识TThread对象

VCL 提供了用于多线程编程的TThread类,在这个类中封装了Windows关于线程机制的Windows API,通常将它的实例成为线程对象。线程对象通过封装简化了多线程应用程序的编写。注意,线程对象不允许控制线程堆栈的大小或安全属性。若需要控制这些,必须使用Windows API的CreateThread()或BeginThread()函数。不过,即使是使用Windows Thread API函数建立和控制多线程,仍然可从一些同步线程对象或下节将要描述的方法中受益。

要在应用程序中使用线程对象,必须创建 TThread的一个派生类。File|New|Thread Object,系统会提示为新线程对象提供类名,我们将其命名为TMyThread。我们必须自行在构造函数以及Execute()函数中添加代码。自动生成的构造函数中有一个参数,如果为true的话线程创建后将进入挂起状态,直到线程对象的Resume()函数被调用才开始执行。如果为false则线程创建后会立刻开始执行。

我们先创建一个实例来亲自感受下多线程:在窗体上放两个Button和两个Edit组件,自动命名。然后File|New|Thread Object来创建一个线程对象,命名为TMyThread。

以下请看完整工程代码:
//Unit1.h         //主窗体头文件

//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include "Unit2.h"
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:     // IDE-managed Components
     TButton *Button1;
     TButton *Button2;
     TEdit *Edit1;
     TEdit *Edit2;
     void __fastcall Button1Click(TObject *Sender);
     void __fastcall Button2Click(TObject *Sender);
     void __fastcall FormCreate(TObject *Sender);
private:     // User declarations
     TMyThread *thread1,*thread2;
public:         // User declarations
     __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

//Unit1.cpp         //主窗体实现文件

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
     : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
     thread1->Resume();     //单击后才启动线程
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
     thread2->Resume();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
     thread1=new TMyThread(true,Edit1);     //创建线程对象实例
     thread2=new TMyThread(true,Edit2);
}
//---------------------------------------------------------------------------

//Unit2.h         //线程类头文件

//---------------------------------------------------------------------------
#ifndef Unit2H
#define Unit2H
//---------------------------------------------------------------------------
#include <Classes.hpp>
//---------------------------------------------------------------------------
class TMyThread : public TThread
{          
private:
     TEdit *edResult;     //自定义局部变量
     String strResult;
protected:
     void __fastcall Execute();
     void __fastcall ShowResult();         //自定义函数
public:
     __fastcall TMyThread(bool CreateSuspended,TEdit *AEdit);     //注意:修改了默认参数
};
//---------------------------------------------------------------------------
#endif

//Unit2.cpp         //线程类实现文件

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "Unit2.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
__fastcall TMyThread::TMyThread(bool CreateSuspended,TEdit *AEdit)
     : TThread(CreateSuspended)
{
     edResult=AEdit;
}
//---------------------------------------------------------------------------
void __fastcall TMyThread::Execute()
{
     for(int i=0;i<200;i++)
     {
         strResult=IntToStr(i);
         Synchronize(ShowResult);     //管理线程同步,保证安全性
         Sleep(100);
     }
}
//---------------------------------------------------------------------------
void __fastcall TMyThread::ShowResult()
{
     edResult->Text=strResult;
}
//---------------------------------------------------------------------------

然后我们F9运行程序就可以查看效果了。

二、编写线程函数

Execute ()函数就是线程函数,它包含了程序中所有需要并行执行的代码。除了共享相同的进程空间外,可以认为线程就是通过应用程序启动的程序。但在编写线程函数的时候需要注意与单独程序的不同之处。因为线程与其他线程共享内存空间,所以必须确认没有覆盖应用程序中其它线程的内存地址。而另一方面,可以使用共享内存在线程之间进行通信。

在线程函数内部,我们可以使用任意的全局变量,但有些变量我们并不希望同一线程类的其他实例共享它,就可以声明一个线程(thread-local)变量。通过将__thread修饰语加入变量声明就可以声明一个线程变量。例如 int __thread x; 声明一个整型变量。

__thread修饰语只可用于全局(文件范围)或静态变量。指针和函数变量不能作为线程变量。使用“在写入时复制”语法的类,如AnsiStrings也不能作为线程变量。需要在运行时进行初始化或析构的类型也不能被声明为__thread类型。

当程序中调用Resume()函数时,线程启动并继续执行直到Execute()结束。这就是线程执行特定任务,并在其完成时终止的模式。然而,有时应用程序需在一些外部条件满足时终止线程。通过检查Terminated属性可允许其它线程通知本线程终止。当其它线程试图终止本线程时,它调用 Terminate()函数。Terminate()函数将本线程的Terminated属性设置为true。Execute()函数通过检查和响应 Terminated属性来实现Terminate()函数。下面的实例演示了这种做法:
void __fastcall TMyThread::Execute()
{
     while( !Terminated )
     {
     }
}

在线程函数终止时我们可能需要做一些清理工作。由于在线程终止前,OnTerminate事件会发生,所以我们可以将清理代码放在OnTerminate事件处理程序中,这样可确保不管Execute()函数如何执行,清理代码总是可以被执行。要注意OnTerminate事件处理程序不作为线程的一部分运行,而是在应用程序的主线程中执行的。这意味着:
(1)在OnTerminate事件处理程序中不能使用任何线程局部变量。
(2)在OnTerminate事件处理程序中可安全地访问任何组件及VCL对象而不会和其他线程发生冲突。

三、协调线程

在编写线程执行时运行的代码时,必须考虑到可能同步执行的其他线程行为。主要有两种情况:一个是避免两个线程试图同时使用某一个全局对象或变量;另一个是某线程中的一些代码可能会依赖其他线程所执行任务的结果。

1,避免同时访问
为避免在访问全局对象或变量时与其他线程发生冲突,可能需要暂停其他线程的执行,直到该线程代码完成操作。这里需要注意,不要暂停其他不需停止的线程执行,这样会使效率严重降低,也无法获得使用多线程的优点。
  
     <1>,锁定对象
     一些对象内置了锁定功能,以防止其他线程使用该对象的实例。例如,画布对象(TCanvas及其派生类)有一种Lock()函数可防止其他线程访问画布,直到调用Unlock()函数。
     VCL还包含一种线程安全的列表对象TThreadList。调用TThreadList::LockList()返回列表对象,同时组织其他线程使用列表直到调用UnlockList()函数。调用TCanvas::Lock()函数或TThreadList::LockList()函数时可以安全地嵌套。锁定直到最后一个锁定调用匹配到同一线程中相应的解锁调用时才会被释放。
     显然这种方法只对部分类有效。
  
     <2>,使用重要区段
     若对象没有提供内置的锁定功能,可使用重要区段。重要区段像门一样,每次只允许一个线程进入。要使用它,需创建TCriticalSection的全局实例。TCriticalSection有两个函数:Acquire()(阻止其他线程执行该区段)以Release()(取消对其他线程的阻止)。
     每个重要区段都与需要保护的全局内存关联。每个要访问这个全局内存的线程首先要调用Acquire()函数以确保其他线程不能访问它。当线程结束时,要调用Release()函数以便其他线程能继续访问。
     例如,应用程序有一个全局重要区段变量pLockXY,可阻止访问全局变量X和Y。任何使用X或Y的线程必须调用重要区段,如下所示:
     pLockXY->Acquire();
     try{
     Y=sin(X);
     }
     __finally
     {
     pLockXY->Release();
     }
  
     <3>,使用多重读、独占写的同步器
     当使用重要区段来保护全局内存时,每次只有一个线程可以使用该内容。这种保护可能超出了需要,特别是当有一个经常读但很少写的对象或变量时更是如此。多个线程同时读相同内存但没有线程写内存是没有危险的。当有一些经常被读但很少有线程向其写入的全局内存时,可使用 TMultiReadExclusiveWriteSynchronizer对象保护它。这个对象与重要区段一样,但它允许多个线程同时读,只要没有线程写即可。线程必须有独占访问权才能写使用TMultiReadExclusiveWriteSynchronizer保护的内存。
     要使用“多重读、独占写”的同步器,需创建TMultiReadExclusiveWriteSynchronizer的一个全局实例,它与要保护的全局内存关联。每个需要读内存的线程首先要调用BeginRead()函数。它确保当前无其它线程写内存。线程完成读操作后调用EndRead()函数。任何线程要写内存的时候必须先调用BeginWrite()函数,结束后调用EndWrite()函数。
  
     <4>,共享内存的其他技术
     当使用VCL对象时,使用主VCL线程来执行代码,可确保对象不会间接地访问同时被其他线程中的VCL对象使用的内存。若全局变量不需要被多个线程共享,可使用线程变量来代替它。线程可以不需要等待或暂停其他线程。
  
2,等待其他线程
若线程必须等待另一线程完成某项任务,可让线程临时中断执行。然后要么等待另一线程完全执行结束,要么等到另一线程通知完成了该项任务。

<1>,等待线程执行结束
要等待另一线程执行结束,使用它的WaitFor()函数。WaitFor()函数直到那个线程终止才返回,终止的方式要么完成了Execute()函数,要么由于一个异常。例如,下面的代码在访问列表中的对象前等待,直到另一线程填满该列表。
void __fastcall TVisitList::Execute()
{
int fileRes;
TFillThread *fl=new TFillThread(false);
fillRes=f1->WaitFor();
//以下进行后续处理
}
上例中,列表对象只在WaitFor()函数指出该列表被填满时才能被访问。返回值由被等待线程的Execute()函数指定。然而,因为调用 WaitFor()函数的线程需要直到另一线程的执行结果,无法以代码调用Execute()函数,Execute()函数也无法返回任何值。所以 TFillThread线程的Execute()函数应该设置ReturnValue属性。ReturnValue通过被其他线程调用的WaitFor ()函数返回。返回值是一个证书,由应用程序确定其含意。

<2>,等待任务完成
有时,只需等待线程完成一些操作而不是执行结束。为此,可使用一个事件对象。事件对象(TEvent)应具有全局范围以便他们能够为所有线程可见。当一个线程完成一个被其他线程依赖的操作时,调用TEvent::SetEvent()函数。它发出一个信号,以便任何其他线程可检查并得知操作完成。要关掉信号则使用ResetEvent() 函数。

四、调试多线程程序

当调试多线程应用程序时,试图跟踪所有并行线程的状态,或在断点停止时判断是哪一个线程的执行往往会使人感到迷惑。可使用Thread Status框来帮助跟踪并控制应用程序中所有的线程。开启Thread Status框的方法是:View|Debug Windows|Threads。

当一个调试事件(断点、异常、暂停)发生时,线程状态指示各个线程的状态。右击可定位相应的源代码位置或将其他线程设置为当前线程等。

最后要提醒的是,不要使用无意义的多线程。如果一段程序完全是串行的,每一步的操作都需要上一步的结果,那么在这里采用多线程技术就是毫无意义的多线程编程是提高系统资源利用率的一种常见方式。它占用的资源更小,启动更快,还可以实现在后台运行一些需时较长的操作。

一、初识TThread对象

VCL 提供了用于多线程编程的TThread类,在这个类中封装了Windows关于线程机制的Windows API,通常将它的实例成为线程对象。线程对象通过封装简化了多线程应用程序的编写。注意,线程对象不允许控制线程堆栈的大小或安全属性。若需要控制这些,必须使用Windows API的CreateThread()或BeginThread()函数。不过,即使是使用Windows Thread API函数建立和控制多线程,仍然可从一些同步线程对象或下节将要描述的方法中受益。

要在应用程序中使用线程对象,必须创建 TThread的一个派生类。File|New|Thread Object,系统会提示为新线程对象提供类名,我们将其命名为TMyThread。我们必须自行在构造函数以及Execute()函数中添加代码。自动生成的构造函数中有一个参数,如果为true的话线程创建后将进入挂起状态,直到线程对象的Resume()函数被调用才开始执行。如果为false则线程创建后会立刻开始执行。

我们先创建一个实例来亲自感受下多线程:在窗体上放两个Button和两个Edit组件,自动命名。然后File|New|Thread Object来创建一个线程对象,命名为TMyThread。

以下请看完整工程代码:
//Unit1.h         //主窗体头文件

//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include "Unit2.h"
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:     // IDE-managed Components
     TButton *Button1;
     TButton *Button2;
     TEdit *Edit1;
     TEdit *Edit2;
     void __fastcall Button1Click(TObject *Sender);
     void __fastcall Button2Click(TObject *Sender);
     void __fastcall FormCreate(TObject *Sender);
private:     // User declarations
     TMyThread *thread1,*thread2;
public:         // User declarations
     __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

//Unit1.cpp         //主窗体实现文件

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
     : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
     thread1->Resume();     //单击后才启动线程
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
     thread2->Resume();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
     thread1=new TMyThread(true,Edit1);     //创建线程对象实例
     thread2=new TMyThread(true,Edit2);
}
//---------------------------------------------------------------------------

//Unit2.h         //线程类头文件

//---------------------------------------------------------------------------
#ifndef Unit2H
#define Unit2H
//---------------------------------------------------------------------------
#include <Classes.hpp>
//---------------------------------------------------------------------------
class TMyThread : public TThread
{          
private:
     TEdit *edResult;     //自定义局部变量
     String strResult;
protected:
     void __fastcall Execute();
     void __fastcall ShowResult();         //自定义函数
public:
     __fastcall TMyThread(bool CreateSuspended,TEdit *AEdit);     //注意:修改了默认参数
};
//---------------------------------------------------------------------------
#endif

//Unit2.cpp         //线程类实现文件

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "Unit2.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
__fastcall TMyThread::TMyThread(bool CreateSuspended,TEdit *AEdit)
     : TThread(CreateSuspended)
{
     edResult=AEdit;
}
//---------------------------------------------------------------------------
void __fastcall TMyThread::Execute()
{
     for(int i=0;i<200;i++)
     {
         strResult=IntToStr(i);
         Synchronize(ShowResult);     //管理线程同步,保证安全性
         Sleep(100);
     }
}
//---------------------------------------------------------------------------
void __fastcall TMyThread::ShowResult()
{
     edResult->Text=strResult;
}
//---------------------------------------------------------------------------

然后我们F9运行程序就可以查看效果了。

二、编写线程函数

Execute ()函数就是线程函数,它包含了程序中所有需要并行执行的代码。除了共享相同的进程空间外,可以认为线程就是通过应用程序启动的程序。但在编写线程函数的时候需要注意与单独程序的不同之处。因为线程与其他线程共享内存空间,所以必须确认没有覆盖应用程序中其它线程的内存地址。而另一方面,可以使用共享内存在线程之间进行通信。

在线程函数内部,我们可以使用任意的全局变量,但有些变量我们并不希望同一线程类的其他实例共享它,就可以声明一个线程(thread-local)变量。通过将__thread修饰语加入变量声明就可以声明一个线程变量。例如 int __thread x; 声明一个整型变量。

__thread修饰语只可用于全局(文件范围)或静态变量。指针和函数变量不能作为线程变量。使用“在写入时复制”语法的类,如AnsiStrings也不能作为线程变量。需要在运行时进行初始化或析构的类型也不能被声明为__thread类型。

当程序中调用Resume()函数时,线程启动并继续执行直到Execute()结束。这就是线程执行特定任务,并在其完成时终止的模式。然而,有时应用程序需在一些外部条件满足时终止线程。通过检查Terminated属性可允许其它线程通知本线程终止。当其它线程试图终止本线程时,它调用 Terminate()函数。Terminate()函数将本线程的Terminated属性设置为true。Execute()函数通过检查和响应 Terminated属性来实现Terminate()函数。下面的实例演示了这种做法:
void __fastcall TMyThread::Execute()
{
     while( !Terminated )
     {
     }
}

在线程函数终止时我们可能需要做一些清理工作。由于在线程终止前,OnTerminate事件会发生,所以我们可以将清理代码放在OnTerminate事件处理程序中,这样可确保不管Execute()函数如何执行,清理代码总是可以被执行。要注意OnTerminate事件处理程序不作为线程的一部分运行,而是在应用程序的主线程中执行的。这意味着:
(1)在OnTerminate事件处理程序中不能使用任何线程局部变量。
(2)在OnTerminate事件处理程序中可安全地访问任何组件及VCL对象而不会和其他线程发生冲突。

三、协调线程

在编写线程执行时运行的代码时,必须考虑到可能同步执行的其他线程行为。主要有两种情况:一个是避免两个线程试图同时使用某一个全局对象或变量;另一个是某线程中的一些代码可能会依赖其他线程所执行任务的结果。

1,避免同时访问
为避免在访问全局对象或变量时与其他线程发生冲突,可能需要暂停其他线程的执行,直到该线程代码完成操作。这里需要注意,不要暂停其他不需停止的线程执行,这样会使效率严重降低,也无法获得使用多线程的优点。
  
     <1>,锁定对象
     一些对象内置了锁定功能,以防止其他线程使用该对象的实例。例如,画布对象(TCanvas及其派生类)有一种Lock()函数可防止其他线程访问画布,直到调用Unlock()函数。
     VCL还包含一种线程安全的列表对象TThreadList。调用TThreadList::LockList()返回列表对象,同时组织其他线程使用列表直到调用UnlockList()函数。调用TCanvas::Lock()函数或TThreadList::LockList()函数时可以安全地嵌套。锁定直到最后一个锁定调用匹配到同一线程中相应的解锁调用时才会被释放。
     显然这种方法只对部分类有效。
  
     <2>,使用重要区段
     若对象没有提供内置的锁定功能,可使用重要区段。重要区段像门一样,每次只允许一个线程进入。要使用它,需创建TCriticalSection的全局实例。TCriticalSection有两个函数:Acquire()(阻止其他线程执行该区段)以Release()(取消对其他线程的阻止)。
     每个重要区段都与需要保护的全局内存关联。每个要访问这个全局内存的线程首先要调用Acquire()函数以确保其他线程不能访问它。当线程结束时,要调用Release()函数以便其他线程能继续访问。
     例如,应用程序有一个全局重要区段变量pLockXY,可阻止访问全局变量X和Y。任何使用X或Y的线程必须调用重要区段,如下所示:
     pLockXY->Acquire();
     try{
     Y=sin(X);
     }
     __finally
     {
     pLockXY->Release();
     }
  
     <3>,使用多重读、独占写的同步器
     当使用重要区段来保护全局内存时,每次只有一个线程可以使用该内容。这种保护可能超出了需要,特别是当有一个经常读但很少写的对象或变量时更是如此。多个线程同时读相同内存但没有线程写内存是没有危险的。当有一些经常被读但很少有线程向其写入的全局内存时,可使用 TMultiReadExclusiveWriteSynchronizer对象保护它。这个对象与重要区段一样,但它允许多个线程同时读,只要没有线程写即可。线程必须有独占访问权才能写使用TMultiReadExclusiveWriteSynchronizer保护的内存。
     要使用“多重读、独占写”的同步器,需创建TMultiReadExclusiveWriteSynchronizer的一个全局实例,它与要保护的全局内存关联。每个需要读内存的线程首先要调用BeginRead()函数。它确保当前无其它线程写内存。线程完成读操作后调用EndRead()函数。任何线程要写内存的时候必须先调用BeginWrite()函数,结束后调用EndWrite()函数。
  
     <4>,共享内存的其他技术
     当使用VCL对象时,使用主VCL线程来执行代码,可确保对象不会间接地访问同时被其他线程中的VCL对象使用的内存。若全局变量不需要被多个线程共享,可使用线程变量来代替它。线程可以不需要等待或暂停其他线程。
  
2,等待其他线程
若线程必须等待另一线程完成某项任务,可让线程临时中断执行。然后要么等待另一线程完全执行结束,要么等到另一线程通知完成了该项任务。

<1>,等待线程执行结束
要等待另一线程执行结束,使用它的WaitFor()函数。WaitFor()函数直到那个线程终止才返回,终止的方式要么完成了Execute()函数,要么由于一个异常。例如,下面的代码在访问列表中的对象前等待,直到另一线程填满该列表。
void __fastcall TVisitList::Execute()
{
int fileRes;
TFillThread *fl=new TFillThread(false);
fillRes=f1->WaitFor();
//以下进行后续处理
}
上例中,列表对象只在WaitFor()函数指出该列表被填满时才能被访问。返回值由被等待线程的Execute()函数指定。然而,因为调用 WaitFor()函数的线程需要直到另一线程的执行结果,无法以代码调用Execute()函数,Execute()函数也无法返回任何值。所以 TFillThread线程的Execute()函数应该设置ReturnValue属性。ReturnValue通过被其他线程调用的WaitFor ()函数返回。返回值是一个证书,由应用程序确定其含意。

<2>,等待任务完成
有时,只需等待线程完成一些操作而不是执行结束。为此,可使用一个事件对象。事件对象(TEvent)应具有全局范围以便他们能够为所有线程可见。当一个线程完成一个被其他线程依赖的操作时,调用TEvent::SetEvent()函数。它发出一个信号,以便任何其他线程可检查并得知操作完成。要关掉信号则使用ResetEvent() 函数。

四、调试多线程程序

当调试多线程应用程序时,试图跟踪所有并行线程的状态,或在断点停止时判断是哪一个线程的执行往往会使人感到迷惑。可使用Thread Status框来帮助跟踪并控制应用程序中所有的线程。开启Thread Status框的方法是:View|Debug Windows|Threads。

当一个调试事件(断点、异常、暂停)发生时,线程状态指示各个线程的状态。右击可定位相应的源代码位置或将其他线程设置为当前线程等。

对于多线程,不要使用无意义的多线程。如果一段程序完全是串行的,每一步的操作都需要上一步的结果,那么在这里采用多线程技术就是毫无意义的。

时间: 2024-10-25 18:34:00

C++Builder 多线程简介以及实现的相关文章

多线程简介及GCD的使用

多线程简介: 对于任意一个iOS应用,程序运行起来后,默认会产生一个主线程(MainThread),主线程专门用来处理UIKit对象的操作,如界面的显示与更新.处理用户事件触发的操作等等.(记忆这点,所有与UI相关的操作都要在主线程中进行) 对于一个App应用来说,之所以需要引入多个线程,很大程度上是由于有一些操作是非常耗时的,例如:发送网络请求并等待服务器的响应,这种耗时操作是不能 够放在主线程中进行操作的,因为在等待的时间内,主线程被使用,用户是不能做任何交互动作的,因而会极大影响用户体验.

iOS开发多线程篇—多线程简介

iOS开发多线程篇-多线程简介 一.进程和线程 1.什么是进程 进程是指在系统中正在执行的一个应用程序 每一个进程之间是独立的.每一个进程均执行在其专用且受保护的内存空间内 比方同一时候打开QQ.Xcode,系统就会分别启动2个进程 通过"活动监视器"能够查看Mac系统中所开启的进程 2.什么是线程 1个进程要想运行任务,必须得有线程(每1个进程至少要有1条线程) 线程是进程的基本运行单元,一个进程(程序)的全部任务都在线程中运行 比方使用酷狗播放音乐.使用迅雷下载电影,都须要在线程中

嵌入式 Linux进程间通信(十一)——多线程简介

嵌入式 Linux进程间通信(十一)--多线程简介 一.线程简介 线程有四种:内核线程.轻量级进程.用户线程.加强版用户线程 1.内核线程 内核线程就是内核的分身,一个分身可以处理一件特定事情.内核线程的使用是廉价的,唯一使用的资源就是内核栈和上下文切换时保存寄存器的空间.支持多线程的内核叫做多线程内核(Multi-Threads kernel ). 2.轻量级进程LWP 轻量级进程(LWP)是一种由内核支持的用户线程,是基于内核线程的高级抽象,只有先支持内核线程,才能有轻量级进程LWP.每一个

c++11 多线程简介

c++11 增加了的多线程的模块 头文件:#include <thread> 常用的几个函数简介 1. join() 该函数主要是运行子线程(并行运行),阻塞主线程,等待所有子线程完成时,继续执行主线程: #include <thread> #include <iostream> #include <Windows.h> using namespace std; void thread01(void) { for (int i = 0; i < 5;

iOS开发-多线程简介

多线程从概念上理解是指从软件或者硬件上实现多个线程并发执行的技术,简单点理解就是同一时间可以执行多个事情(比如说一边听歌一边码代码),听歌是一个线程,码代码是一个线程,如果是单核CPU的话,上面两个动作其实可以确切的理解为并发,也就是伪并行,只是两者相差的时间太快没有察觉.电脑现在一般都是双核的或者四核的,比以往的运算能有提高了不少,iOS中六种可以选择的操作线程的方式,具体方式如下: iOS和OS X线程的底层实现机制是Mach线程,我们基本不会处理线程到这个级别,一般应用中可以使用的线程管理

ios开发,多线程简介

什么是进程? 进程就是指,在系统中正在运行的一个应用程序,比如同时打开QQ,Xcode,系统就会分别启动两个进程. 什么是线程? 一个进程要想执行任务,必须得有线程,线程是进程的基本执行单元,比如使用酷狗播放音乐.使用迅雷下载电影,都需要在线程中执行 线程的串行:一个线程中任务对的执行就是串行 如果要在一个线程中执行多个任务,那么只能一个一个的按照顺序执行这些任务,也就是说,在同一个时间内,一个线程只能执行一个任务 什么是多线程? 一个进程中可以开启多条线程,每条线程可以并发,执行不同的任务 比

“多线程”简介及其C代码实现框架

在一些计算机专业相关的书籍中,大家经常听说"多线程"这个概念.那么什么是"多线程"?什么时候使用"多线程"?在程序设计中使用"多线程"有什么好处呢?很多刚入职的程序员也对"多线程"感到非常的好奇,认为它很"高大上".本文对"多线程"进行了简单的介绍,并给出了其C代码的实现框架. "单线程"程序 要想理解"多线程",那么就要先从&

iOS开发之多线程篇 多线程简介

iOS开发多线程篇—多线程简单介绍 一.进程和线程 1.什么是进程 进程是指系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内 比如同时打开QQ.Xcode,系统就会分别启动2个进程 通过“活动监视器”可以查看Mac系统中所开启的进程 2.什么是线程 1个进程要想执行任务,必须得有线程(每1个进程至少要有1条线程) 线程是进程的基本执行单元,一个进程(程序)的所有任务都在线程中执行 比如使用酷狗播放音乐.使用迅雷下载电影,都需要在线程中执行 3.线程的

iOS多线程简介

1.进程 什么是进程 进程是指在系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内 比如同时打开迅雷.Xcode,系统就会分别启动2个进程 2.线程 什么是线程 1个进程要想执行任务,必须得有线程(每1个进程至少要有1条线程) 一个进程(程序)的所有任务都在线程中执行 比如使用酷狗播放音乐.使用迅雷下载电影,都需要在线程中执行 3.线程的串行 1个线程中任务的执行是串行的 如果要在1个线程中执行多个任务,那么只能一个一个地按顺序执行这些任务 也就是说,