线程池用法的改进

引用: http://blog.csdn.net/jhycjhyc/article/details/7243728

在MSDN关于使用线程池的一个例子(见http://msdn.microsoft.com/en-us/library/3dasc8as(VS.80).aspx).程序如下:

 1 public class Fibonacci
 2 {
 3     public int N { get { return _n; } }
 4     private int _n;
 5
 6     public int FibOfN { get { return _fibOfN; } }
 7     private int _fibOfN;
 8
 9     private ManualResetEvent _doneEvent;
10
11     public Fibonacci(int n, ManualResetEvent doneEvent)
12     {
13         _n = n;
14         _doneEvent = doneEvent;
15     }
16
17     // Wrapper method for use with thread pool.
18     public void ThreadPoolCallback(Object threadContext)
19     {
20
21         int threadIndex = (int)threadContext;
22         Console.WriteLine("thread {0} started...", threadIndex);
23         _fibOfN = Calculate(_n);
24         Console.WriteLine("thread {0} result calculated...", threadIndex);
25         _doneEvent.Set();
26     }
27
28     // Recursive method that calculates the Nth Fibonacci number.
29     public int Calculate(int n)
30     {
31         //Thread thread = Thread.CurrentThread;
32         //Console.WriteLine("[{0}] Calculate:{1}...", thread.ManagedThreadId, n);
33         if (n <= 1)
34         {
35             return n;
36         }
37         return Calculate(n - 1) + Calculate(n - 2);
38     }
39
40 }

调用方法:

 1 static void Main(string[] args)
 2 {
 3     const int FibonacciCalculations = 2;  //最大只能64,超出会报错
 4
 5     // One event is used for each Fibonacci object
 6     ManualResetEvent[] doneEvents = new ManualResetEvent[FibonacciCalculations];
 7     Fibonacci[] fibArray = new Fibonacci[FibonacciCalculations];
 8     Random r = new Random();
 9
10     // Configure and launch threads using ThreadPool:
11     Console.WriteLine("launching {0} tasks...", FibonacciCalculations);
12     for (int i = 0; i < FibonacciCalculations; i++)
13     {
14         doneEvents[i] = new ManualResetEvent(false);
15         Fibonacci f = new Fibonacci(r.Next(20, 40), doneEvents[i]);
16         fibArray[i] = f;
17         ThreadPool.QueueUserWorkItem(new WaitCallback(f.ThreadPoolCallback), i);
18     }
19
20     // Wait for all threads in pool to calculation...
21     WaitHandle.WaitAll(doneEvents);
22     Console.WriteLine("All calculations are complete.");
23
24     // Display the results...
25     for (int i = 0; i < FibonacciCalculations; i++)
26     {
27         Fibonacci f = fibArray[i];
28         Console.WriteLine("Fibonacci({0}) = {1}", f.N, f.FibOfN);
29     }
30     Console.ReadLine();
31 }

以上例子是利用多线程的线程池技术进行批处理的经典范例,在实际应用中稍加改动就可以实现自己所需的功能,但遗憾的是,如果批处理的任务数大于64个时,程序运行就会出错,提示"WaitHandles 的数目必须少于或等于 64 个."以上例而言,将"const int FibonacciCalculations = 10;"改为"const int FibonacciCalculations = 65;"后再运行就会出错,这确实是一个不足,因为在实际工作中很多情况下需要用线程池技术批量处理64个以上的任务,怎么办呢?经过分析,对以上程序做了一些改动,解决了这个问题,而且程序的结构更简单,也不再需要使用 ManualResetEvent 对象,修改后的程序如下:

 1 public class Fibonacci_02
 2 {
 3     public int ifdone = 0;   //注意这里
 4
 5     public int N { get { return _n; } }
 6     private int _n;
 7
 8     public int FibOfN { get { return _fibOfN; } }
 9     private int _fibOfN;
10
11     public Fibonacci_02(int n)
12     {
13         _n = n;
14     }
15
16     // Wrapper method for use with thread pool.
17     public void ThreadPoolCallback(Object threadContext)
18     {
19         int threadIndex = (int)threadContext;
20         Console.WriteLine("thread {0} started...", threadIndex);
21         _fibOfN = Calculate(_n);
22         Console.WriteLine("thread {0} result calculated...", threadIndex);
23
24         ifdone = 1;
25     }
26
27     // Recursive method that calculates the Nth Fibonacci number.
28     public int Calculate(int n)
29     {
30         //Thread thread = Thread.CurrentThread;
31         //Console.WriteLine("[{0}] Calculate:{1}...", thread.ManagedThreadId, n);
32         if (n <= 1)
33         {
34             return n;
35         }
36         Thread.Sleep(1);
37         return Calculate(n - 1) + Calculate(n - 2);
38     }
39 }

调用方法:

 1 static void Main(string[] args)
 2 {
 3     const int FibonacciCalculations = 2;//可以无限大
 4
 5     // One event is used for each Fibonacci object
 6     Fibonacci_02[] fibArray = new Fibonacci_02[FibonacciCalculations];
 7     Random r = new Random();
 8
 9     // Configure and launch threads using ThreadPool:
10     Console.WriteLine("launching {0} tasks...", FibonacciCalculations);
11     for (int i = 0; i < FibonacciCalculations; i++)
12     {
13         Fibonacci_02 f = new Fibonacci_02(r.Next(20, 40));
14         fibArray[i] = f;
15         ThreadPool.QueueUserWorkItem(new WaitCallback(f.ThreadPoolCallback), i);
16     }
17
18     // Wait for all threads in pool to calculation...
19     //注意这里
20     while (true)
21     {
22         int counts = 0;
23         for (int i = 0; i < FibonacciCalculations; i++) counts = counts + fibArray[i].ifdone;
24         if (counts == FibonacciCalculations) break;
25     }
26     Console.WriteLine("All calculations are complete.");
27
28     // Display the results...
29     for (int i = 0; i < FibonacciCalculations; i++)
30     {
31         Fibonacci_02 f = fibArray[i];
32         Console.WriteLine("Fibonacci({0}) = {1}", f.N, f.FibOfN);
33     }
34     Console.ReadLine();
35 }

时间: 2024-11-12 00:58:27

线程池用法的改进的相关文章

Java常用四大线程池用法以及ThreadPoolExecutor详解

为什么用线程池? 1.创建/销毁线程伴随着系统开销,过于频繁的创建/销毁线程,会很大程度上影响处-理效率 2.线程并发数量过多,抢占系统资源从而导致阻塞 3.对线程进行一些简单的管理 在Java中,线程池的概念是Executor这个接口,具体实现为ThreadPoolExecutor类,学习Java中的线程池,就可以直接学习他了对线程池的配置,就是对ThreadPoolExecutor构造函数的参数的配置 一.ThreadPoolExecutor提供了四个构造函数: //五个参数的构造函数 pu

java 线程池用法

public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) 下面解释下一下构造器中各个参数的含义: corePoolSize:核心池的大小,这个参数跟后面讲述的线程池的实现原理有非常大的关系.在创建了线程池后,默认情况下,线程池中并没有任何线程,而是等待有任务到来才创建线程去执行任务,除

线程池,千万注意,原来很多人都在错用

线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线程池线程都是后台线程.每个线程都使用默认的堆栈大小,以默认的优先级运行. [C#线程池] 场景:以下是C# winform写的一个线程池示例程序.窗体上,分别拖放一个开始和停止按钮,单击开始按钮,for寻觅模拟7000个任务队列,在线程池运行过程中,可以点击停止按钮,来结束线程池所有任务,这里借助CancellationTokenSource对象,来实现线程池的停止. 开始前,请大家看以下代码,有什么问题

Java多线程-新特性-线程池

Sun在Java5中,对Java线程的类库做了大量的扩展,其中线程池就是Java5的新特征之一,除了线程池之外,还有很多多线程相关的内容,为多线程的编程带来了极大便利.为了编写高效稳定可靠的多线程程序,线程部分的新增内容显得尤为重要. 有关Java5线程新特征的内容全部在java.util.concurrent下面,里面包含数目众多的接口和类,熟悉这部分API特征是一项艰难的学习过程.目前有关这方面的资料和书籍都少之又少,大部分介绍线程方面书籍还停留在java5之前的知识层面上. 在Java5之

线程池网络服务

1.线程池网络服务 :针对多线程网络服务模式的一些不足之处而提出的改进模式. 池是一个很重要的概念,其基本理念是:先创建一批资源,当有用户到来时,直接分配以创建好的资源,它的主要目的是减少系统在频繁创建资源时的开销. 实现原理:主服务线程创建既定数量的服务线程,当有客户端到来时,则从线程池中找出空闲的服务线程,为其服务,服务完毕后,线程不进行释放,重新放回线程池:若当前线程池已满,则将当前的客户端加入等待队列. 模型如下: 2.代码实现 同样用处理整数运算来模拟线程池的并发处理 (1).util

《CLR via C#》之线程处理——线程池与任务

<CLR via C#>之线程处理--线程池与任务 <CLR via C#>之线程处理--线程池与任务线程池线程池用法任务等待任务完成并获取结果(Wait方法和Result属性)取消任务(token的ThrowIfCancellationRequested方法)任务完成自动启动新任务(ContinueWith方法)任务启动子任务任务工厂(TaskFactory和TaskFactory) 线程池 每一个CLR都有一个线程池--由这个CLR控制的所有AppDomain共享.如果一个进程

SpringBoot-技术专区-实战方案-应用监控线程池

背景 废话不多说,做这个监控的背景很简单,我们的项目都是以spring boot框架为基础开发的,代码里所有的异步线程都是通过@Async标签标注的,并且标注的时候都是指定对应线程池的,如果不知@Async标注的,可以参考@Async异步线程池用法总结, 如果你用的不是spring,就参考上文提到的公众号文章就好.再回到背景,我们当时经常遇到的问题就是这些线程池的队列满了之后,新的异步任务无法添加进去的错误,因此我们想对所有这种类型的线程池进行监控. 监控方式 再来介绍一下我们最终采用的方式 —

ThreadLocal,LinkedBlockingQueue,线程池 获取数据库连接2改进

package com.ctl.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Random; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import com.ctl.util.ConfigU

java5线程池详解与Executors类创建不同线程池的用法

java中的线程池是非常重要的,它可以节省资源开销,从而提升程序的性能.向Tomcat等一些web服务器都必须用到线程池.java5中为我们提供了一些应用线程池的API,下面的代码将详解其用法. package hxl.insist; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorSer