c++多线程,一个很清晰的包含类定义的多线程实例

/*  file Main.cpp
 *
 *  This program is an adaptation of the code Rex Jaeschke showed in
 *  Listing 1 of his Oct 2005 C/C++ User's Journal article entitled
 *  "C++/CLI Threading: Part I".  I changed it from C++/CLI (managed)
 *  code to standard C++.
 *
 *  One hassle is the fact that C++ must employ a free (C) function
 *  or a static class member function as the thread entry function.
 *
 *  This program must be compiled with a multi-threaded C run-time
 *  (/MT for LIBCMT.LIB in a release build or /MTd for LIBCMTD.LIB
 *  in a debug build).
 *
 *                                      John Kopplin  7/2006
 */


#include <stdio.h>
#include <string>             // for STL string class
#include <windows.h>          // for HANDLE
#include <process.h>          // for _beginthread()

using namespace std;


class ThreadX
{
private:
  int loopStart;
  int loopEnd;
  int dispFrequency;

public:
  string threadName;

  ThreadX( int startValue, int endValue, int frequency )
  {
    loopStart = startValue;
    loopEnd = endValue;
    dispFrequency = frequency;
  }

  // In C++ you must employ a free (C) function or a static
  // class member function as the thread entry-point-function.
  // Furthermore, _beginthreadex() demands that the thread
  // entry function signature take a single (void*) and returned
  // an unsigned.
  static unsigned __stdcall ThreadStaticEntryPoint(void * pThis)
  {
      ThreadX * pthX = (ThreadX*)pThis;   // the tricky cast
      pthX->ThreadEntryPoint();           // now call the true entry-point-function

      // A thread terminates automatically if it completes execution,
      // or it can terminate itself with a call to _endthread().

      return 1;          // the thread exit code
  }

  void ThreadEntryPoint()
  {
     // This is the desired entry-point-function but to get
     // here we have to use a 2 step procedure involving
     // the ThreadStaticEntryPoint() function.

    for (int i = loopStart; i <= loopEnd; ++i)
    {
      if (i % dispFrequency == 0)
      {
          printf( "%s: i = %d\n", threadName.c_str(), i );
      }
    }
    printf( "%s thread terminating\n", threadName.c_str() );
  }
};


int main()
{
    // All processes get a primary thread automatically. This primary
    // thread can generate additional threads.  In this program the
    // primary thread creates 2 additional threads and all 3 threads
    // then run simultaneously without any synchronization.  No data
    // is shared between the threads.

    // We instantiate an object of the ThreadX class. Next we will
    // create a thread and specify that the thread is to begin executing
    // the function ThreadEntryPoint() on object o1. Once started,
    // this thread will execute until that function terminates or
    // until the overall process terminates.

    ThreadX * o1 = new ThreadX( 0, 1000000, 20000 );

    // When developing a multithreaded WIN32-based application with
    // Visual C++, you need to use the CRT thread functions to create
    // any threads that call CRT functions. Hence to create and terminate
    // threads, use _beginthreadex() and _endthreadex() instead of
    // the Win32 APIs CreateThread() and EndThread().

    // The multithread library LIBCMT.LIB includes the _beginthread()
    // and _endthread() functions. The _beginthread() function performs
    // initialization without which many C run-time functions will fail.
    // You must use _beginthread() instead of CreateThread() in C programs
    // built with LIBCMT.LIB if you intend to call C run-time functions.

    // Unlike the thread handle returned by _beginthread(), the thread handle
    // returned by _beginthreadex() can be used with the synchronization APIs.

    HANDLE   hth1;
    unsigned  uiThread1ID;

    hth1 = (HANDLE)_beginthreadex( NULL,         // security
                                   0,            // stack size
                                   ThreadX::ThreadStaticEntryPoint,
                                   o1,           // arg list
                                   CREATE_SUSPENDED,  // so we can later call ResumeThread()
                                   &uiThread1ID );

    if ( hth1 == 0 )
        printf("Failed to create thread 1\n");

    DWORD   dwExitCode;

    GetExitCodeThread( hth1, &dwExitCode );  // should be STILL_ACTIVE = 0x00000103 = 259
    printf( "initial thread 1 exit code = %u\n", dwExitCode );

    // The System::Threading::Thread object in C++/CLI has a "Name" property.
    // To create the equivalent functionality in C++ I added a public data member
    // named threadName.

    o1->threadName = "t1";

    ThreadX * o2 = new ThreadX( -1000000, 0, 20000 );

    HANDLE   hth2;
    unsigned  uiThread2ID;

    hth2 = (HANDLE)_beginthreadex( NULL,         // security
                                   0,            // stack size
                                   ThreadX::ThreadStaticEntryPoint,
                                   o2,           // arg list
                                   CREATE_SUSPENDED,  // so we can later call ResumeThread()
                                   &uiThread2ID );

    if ( hth2 == 0 )
        printf("Failed to create thread 2\n");

    GetExitCodeThread( hth2, &dwExitCode );  // should be STILL_ACTIVE = 0x00000103 = 259
    printf( "initial thread 2 exit code = %u\n", dwExitCode );

    o2->threadName = "t2";

    // If we hadn't specified CREATE_SUSPENDED in the call to _beginthreadex()
    // we wouldn't now need to call ResumeThread().

    ResumeThread( hth1 );   // serves the purpose of Jaeschke's t1->Start()

    ResumeThread( hth2 );

    // In C++/CLI the process continues until the last thread exits.
    // That is, the thread's have independent lifetimes. Hence
    // Jaeschke's original code was designed to show that the primary
    // thread could exit and not influence the other threads.

    // However in C++ the process terminates when the primary thread exits
    // and when the process terminates all its threads are then terminated.
    // Hence if you comment out the following waits, the non-primary
    // threads will never get a chance to run.

    WaitForSingleObject( hth1, INFINITE );
    WaitForSingleObject( hth2, INFINITE );

    GetExitCodeThread( hth1, &dwExitCode );
    printf( "thread 1 exited with code %u\n", dwExitCode );

    GetExitCodeThread( hth2, &dwExitCode );
    printf( "thread 2 exited with code %u\n", dwExitCode );

    // The handle returned by _beginthreadex() has to be closed
    // by the caller of _beginthreadex().

    CloseHandle( hth1 );
    CloseHandle( hth2 );

    delete o1;
    o1 = NULL;

    delete o2;
    o2 = NULL;

    printf("Primary thread terminating.\n");
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++线程可以应用于各种场景,以下是一个简单的多线程应用实例: 假设我们有一个任务,需要计算一个数组中所有元素的平方和。我们可以使用多线程来加速计算过程。 首先,我们创建一个包含大量元素的数组,并将其分成几个部分。然后,我们创建多个线程,每个线程负责计算其中一部分数组元素的平方和。最后,将每个线程计算得到的结果相加,即可得到整个数组的平方和。 下面是一个简单的示例代码: ```cpp #include <iostream> #include <thread> #include <vector> // 计算数组部分元素的平方和 int calculateSum(const std::vector<int>& arr, int start, int end) { int sum = 0; for (int i = start; i < end; ++i) { sum += arr[i] * arr[i]; } return sum; } int main() { std::vector<int> arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int numThreads = 4; // 假设使用4个线程 std::vector<std::thread> threads; std::vector<int> partialSums(numThreads); // 创建并启动多个线程 for (int i = 0; i < numThreads; ++i) { int start = i * arr.size() / numThreads; int end = (i + 1) * arr.size() / numThreads; threads.emplace_back([start, end, &arr, &partialSums, i]() { partialSums[i] = calculateSum(arr, start, end); }); } // 等待所有线程完成 for (auto& thread : threads) { thread.join(); } // 计算最终结果 int totalSum = 0; for (int sum : partialSums) { totalSum += sum; } std::cout << "数组的平方和为:" << totalSum << std::endl; return 0; } ``` 在上述示例中,我们使用了`std::thread`来创建多个线程,并使用`std::vector`来保存每个线程计算得到的部分结果。最后,我们将所有部分结果相加得到最终结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值