一个使用线程池的范例(翻译)

一个使用线程池的范例

                                                                             翻译 BY LWKL

                                                                             A programming model to use a thread pool by SherwoodHu

介绍

许多场合我们需要利用多线程来提高我们系统的行为。每个线程序几乎相同,但我们必须管理这些线程。如果当系统繁忙了,那么我们将建立更多的线程序,不然我们杀掉一写来避免额外的负担。

我做了些涉及到多线程序管理的工作,最终我决定写一个来包装这些机制的类。此类能动态的分配线程和分配工作给这些线程。你只需要派生你自己的类,而并不需要知道内部的机制是如何操控制这多个线程和同步这些线程的。然而你必须保证你的工作类必须是线程安全的,原因是你的工作每时每刻都可能会被分派给不同的线程序。

另外,我还想描述下如何使用完成端口,我发现它极其简单和有用,特别是用作传在线程之间传输数据时。

使用

要使用这个线程池类你必须从IWorker接口派生你的工作(WORK)类,从IJobDesc派生你的任务描述(JOB)类。工作的逻辑必须被包括在成员函数IWorker::ProcessJob(IJobDesc* pJob).,此后,你能像这样声明一个线程池:

CThreadPool pool;

pool.Start(6, 10);

//do some other jobs here

pool.Stop();

start函数拥有2个参数,第一个参数是线程池产生的最少线程个数。第2个参数指出最多工作线程的可能数。一方面如果线程序池非常繁忙,它就会自动产生更多的线程序,另一方面,当线程池空闲时,一些线程就会从池中被移走。好好设定这2个参数以便达到更好的表现。

如果想分配给工作给线程池,那么你只需简单的调用以下函数

pool.ProcessJob(pJob, pWorker);

你必须确保你继承的类是线程安全的,因为有可能一个工作实例可能同时工作在多线程里,你在任何情况下都无法得知工作是否工作在相同线程里。

提示

如果你个工作过程非常耗时,那当你调用stop函数的时候,工作并不会立即停止。STOP函数将最多等待超过2分钟然后返回。此函数有一个可选参数,如果参数设定为TRUE,函数不管怎样都会停止这些工作线程。如果参数设定为FALSE,调这些工作线程将不会被野蛮的终止而回继续处在活动状态,在此情况下,你必须小心对待这些工作对象,当你调用STOP()后,如过你试图接近他们有可能你将会得到一个访问错误。

JOB对象必须有new操作符在堆上产生。结束后他将回自动被框架内部DELETE

Sherwood Hu

 

 

评论

有内存泄露

当我使用时候有一些内存泄露

ATL SERVER提供他自己的线程池类。

VS7及起以上版本,你可以使用内部的类 ATL::CThreadPool.工作原型以模板提供,应用3个共用方法和一个TYPEDEF定义工作项目。他非常通用,简单和速度快。当编写WINDOWS程序使用此类代替。

修正BUG

HI

首先非常感谢你分享你的代码

我想有一点BUGWORKERPROC  接近(PROCESS RemoveThread 信息(0xFFFFFFFE)的时候.,当线程接受到这个消息时候,整个的过程结束,线程序被终止。我们并不知道Processjob有没有完成。

所以我像这样修正了

 

 

修正
unsigned int CThreadPool::WorkerProc(void* p)
{

   {
   ...
   bool bBusy = false;
   ...

   while(::GetQueuedCompletionStatus(IoPort, &pN1, &pN2, &pOverLapped, INFINITE ))
   {
      if(pOverLapped == (OVERLAPPED*)0xFFFFFFFE)
      {
         if(bBusy == false)
         {
         TRACE1("Server remove thread ID %d/n", threadId);
         pServer->RemoveThread(threadId);
         break;
         }

        else
           TRACE1("Server remove thread ID %d BUSY/n", threadId);

      }

      else if(pOverLapped == (OVERLAPPED*)0xFFFFFFFF)
      {
      break;
      }

      else
      {
      ...
      bBusy = true;
      pIWorker->ProcessJob(pIJob);
      bBusy = false;
      ....
     }

   }
}

 

 

原地址

http://www.codeproject.com/threads/threadpool.asp

 

 

还有另外一个人做了些修正

详细请看地址

http://www.codeproject.com/threads/error_about_worker_thread.asp

另外一个问题,此处完成端口使用线程池的技术并不是先创建一个完成端口然后将他和一个句柄联系起来。而是使用了先创建一个完成端口,以后所有的工作都使用PostQueuedCompletionStatus 来传递参数和进行线程池内活动。大家看代码时候要注意下

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`CompletableFuture`是Java 8中引入的一个非常强大的工具,用于处理异步计算和并行执行。它提供了一种线程安全的方式来处理异步操作的结果,简化了回调地狱。以下是一个简单的范例,展示如何使用`CompletableFuture`执行异步任务: ```java import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; public class CompletableFutureExample { public static void main(String[] args) throws ExecutionException, InterruptedException { // 创建一个异步任务 CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { System.out.println("开始计算"); // 模拟耗时操作,这里我们只是简单休眠 Thread.sleep(2000); return "异步任务的结果"; }); // 主线程继续执行,不会阻塞 System.out.println("主线程正在执行其他任务..."); // 当异步任务完成后,获取结果 String result = future.get(); // 或者用future.thenApply(result -> ...) System.out.println("最终结果: " + result); } } ``` 在这个例子中: 1. `CompletableFuture.supplyAsync()`方法创建了一个异步任务,它在后台线程中执行,返回一个`CompletableFuture`对象。 2. `Thread.sleep(2000)`模拟了一个延迟执行的任务,实际应用中可能是数据库查询、网络请求等耗时操作。 3. `future.get()`会阻塞,直到异步任务完成并获取结果。如果不希望阻塞,可以使用`thenApply()`、`thenAccept()`或`thenRun()`等方法来处理结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值