关于线程池ThreadPool的学习
学习重点ThreadPool.SetMinThreads(out workerThreads, out completionPortThreads).这是整个线程池的关键。 而ThreadPool.SetMaxThreads(out workerThreads, out completionPortThreads)这个方法在你的线程总数低于1000时是不需要动它的。因为它的默认值就是1023,1000。然后在实际使用的时候只靠客户端发大量线程来处理问题是不一定能降低实际执行时间的,有时候还和服务器端、数据库有关系。
首先谈一下学习的背景,因为一箱货里有几百件产品。用一条SQL语句来检查这几百件产品是否合格,搜索数据对比规格后出结果耗费的时间在7~12秒的时间。现场的操作环境是一箱一箱货不停的扫描的。7~12秒的处理时间导致两箱货的扫描间隔达到10秒之多这是无法接受的。在这种情况下首先想到的是用多线程同时处理所有产品的数据。
List<System.Threading.Thread> list = new List<System.Threading.Thread>();
foreach (DataRow row in ds.Tables[].Rows)
{
//cellname = row[0].ToString(); System.Threading.Thread s1 = new System.Threading.Thread(QueryOCVTime);
list.Add(s1);
s1.Start(row[].ToString());
}
bool IsOver = true;
while (IsOver)
{
for (int i = ; i < list.Count; i++)
{
if (list[i].IsAlive)
{
System.Threading.Thread.Sleep();
break;
}
else if (i == (list.Count - ))
{
IsOver = false;
}
} }
代码一Thread
经过测试处理时间已经降到3~5秒了。但是离需求(1秒以内)还有很大的差距。而且也测试了单线程的执行时间才100毫秒,按逻辑来分析我几乎是同时发出所有的单线程来执行,总的执行时间应该也是100毫秒左右。所以线程都是所以就想到了线程池
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; using System.IO;
using System.Net;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
private static List<string> list;
private static DateTime dt1;
static void Main(string[] args)
{
int maxworkthreads, maxportthreads, minworkthreads, minportthreads;
Console.WriteLine("修改前");
ThreadPool.GetMaxThreads(out maxworkthreads, out maxportthreads);
ThreadPool.GetMinThreads(out minworkthreads, out minportthreads);
Console.WriteLine(maxworkthreads.ToString() + "\t" + maxportthreads.ToString());
Console.WriteLine(minworkthreads.ToString() + "\t" + minportthreads.ToString());
//public static bool SetMinThreads(int workerThreads, int completionPortThreads);
//最关键的修改参数
//workerThreads
//这个值决定了同时执行的最大线程数,超过这个数量就要排队。
//这个值不是越大越好,要综合考虑单线程在进行什么样的操作。
ThreadPool.SetMinThreads(, minportthreads);
Console.WriteLine("修改后");
ThreadPool.GetMaxThreads(out maxworkthreads, out maxportthreads);
ThreadPool.GetMinThreads(out minworkthreads, out minportthreads);
Console.WriteLine(maxworkthreads.ToString() + "\t" + maxportthreads.ToString());
Console.WriteLine(minworkthreads.ToString() + "\t" + minportthreads.ToString());
list = new List<string>();
dt1 = DateTime.Now;
for (int i = ; i < ; i++)
{
//开始执行单线程
ThreadPool.QueueUserWorkItem(new WaitCallback(RunThread), i.ToString());
} bool IsOver = true;
while (IsOver)
{
//检测所有单线程是否执行完毕
int maxthreads, threads, workthreads;
ThreadPool.GetMaxThreads(out maxthreads, out threads);
ThreadPool.GetAvailableThreads(out workthreads, out threads);
if ((maxthreads - workthreads) == )
{
IsOver = false;
}
else
{
Thread.Sleep();
}
}
DateTime dt2 = DateTime.Now;
//运行完毕将执行过程打印出来以便于分析
for (int i = ; i < list.Count; i++)
{
Console.WriteLine(list[i]);
} Console.WriteLine("流程已经运行完毕一共耗时{0}", (dt2 - dt1).TotalSeconds.ToString("0.000")); Console.ReadKey();
}
private static void RunThread(object obj)
{ DateTime dt2 = DateTime.Now;
//假定单线程的处理时间是800毫秒
Thread.Sleep();
DateTime dt3 = DateTime.Now;
//记录下线程和执行时间的信息到后面再打印出来,以免执行时间在打印时浪费而影响测试结果
list.Add(string.Format("{0},thread {1}\t,启动时间{2},耗时 {3},总耗时 {4}",
obj.ToString(),
Thread.CurrentThread.ManagedThreadId,
(dt2 - dt1).TotalSeconds.ToString("0.000"),
(dt3 - dt2).TotalSeconds.ToString("0.000"),
(dt3 - dt1).TotalSeconds.ToString("0.000")
)
); }
}
}
ThreadPool
“public static bool SetMinThreads(int workerThreads, int completionPortThreads);”。这个SetMinThreads(out workerThreads, out completionPortThreads)方法是整个线程池的关键。WorkThreads是指最大活动线程数(即可同时执行的最大线程数),completionPortThreads是指最大IO线程数(即可同时执行的最大IO)。WorkThreads的大小影响整个流程的结束时间,如果单个线程需要10毫秒才能执行完,一共有10个线程并且把WorkThreads设置为5,那么整个流程的完成时间在20毫秒左右。即是单个线程的2倍时间。即执行时间=总线程数/WorkThreads * 单流程时间。
这段测试代码的执行结果是非常理想的。
98,thread 107 ,启动时间0.219,耗时 0.801,总耗时 1.020
99,thread 108 ,启动时间0.225,耗时 0.801,总耗时 1.026
流程已经运行完毕一共耗时1.11
但是在将这段代码移植到实际情况中时结果令人很沮丧。仍然还是要2~3秒才能出结果。仔细查看输出结果不难发现其中的问题
1,thread 6 ,启动时间0.247,耗时 0.309,总耗时 0.556
2,thread 22 ,启动时间0.270,耗时 0.291,总耗时 0.561
......
39,thread 53 ,启动时间0.372,耗时 1.389,总耗时 1.761
40,thread 55 ,启动时间0.372,耗时 1.394,总耗时 1.766
......
50,thread 61 ,启动时间0.374,耗时 1.610,总耗时 1.984
63,thread 63 ,启动时间0.373,耗时 1.677,总耗时 2.050
从上面的输出结果可以看出来在实际的使用环境中,虽然所有线程的启动时间相差是不大的,但是执行时间相差太多了从第1个线程才0.309秒到最后一个线程达到了1.677秒。表明同时执行的线程越多,到后面的线程执行的效率就越慢。导致最后的总执行时间就超出我们的预期了。
这里导致执行效率慢的原因已经不再是线程的问题了。而有可能是数据库的IO或服务器的IO有限制。客户端同时发出大量的请求查找数据,但是在服务端或者在数据库这些同时发出来的线程出现排队的情况了。这个结论是我经过大量测试后得出来的,在后期如果有条件再来验证这个想法。
关于线程池ThreadPool的学习的更多相关文章
- 对于线程池ThreadPool的学习总结
线程池:就是一个管理线程的池子. 优点: 它帮我们管理线程,避免增加创建线程和销毁线程的资源损耗.因为线程其实也是一个对象,创建一个对象,需要经过类加载过程,销毁一个对象,需要走GC垃圾回收流程,都是 ...
- java核心知识点学习----重点学习线程池ThreadPool
线程池是多线程学习中需要重点掌握的. 系统启动一个新线程的成本是比较高的,因为它涉及与操作系统交互.在这种情形下,使用线程池可以很好的提高性能,尤其是当程序中需要创建大量生存期很短暂的线程时,更应该考 ...
- C#多线程学习 之 线程池[ThreadPool](转)
在多线程的程序中,经常会出现两种情况: 一种情况: 应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应 这一般使用ThreadPo ...
- C#多线程学习 之 线程池[ThreadPool]
在多线程的程序中,经常会出现两种情况: 一种情况: 应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应 这一般使用ThreadPo ...
- [转]C#多线程学习 之 线程池[ThreadPool]
在多线程的程序中,经常会出现两种情况: 一种情况: 应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应 这一般使用ThreadPo ...
- 多线程系列 线程池ThreadPool
上一篇文章我们总结了多线程最基础的知识点Thread,我们知道了如何开启一个新的异步线程去做一些事情.可是当我们要开启很多线程的时候,如果仍然使用Thread我们需要去管理每一个线程的启动,挂起和终止 ...
- 多线程系列(2)线程池ThreadPool
上一篇文章我们总结了多线程最基础的知识点Thread,我们知道了如何开启一个新的异步线程去做一些事情.可是当我们要开启很多线程的时候,如果仍然使用Thread我们需要去管理每一个线程的启动,挂起和终止 ...
- 线程池ThreadPool实战
线程池ThreadPool 线程池概念 常用线程池和方法 1.测试线程类 2.newFixedThreadPool固定线程池 3.newSingleThreadExecutor单线程池 4.newCa ...
- 线程池ThreadPool的初探
一.线程池的适用范围 在日常使用多线程开发的时候,一般都构造一个Thread示例,然后调用Start使之执行.如果一个线程它大部分时间花费在等待某个事件响应的发生然后才予以响应:或者如果在一定期间内重 ...
随机推荐
- Cut the Cake(大数相乘)
MMM got a big big big cake, and invited all her M friends to eat the cake together. Surprisingly o ...
- -_-#【jQuery】data
.data() <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <t ...
- Android 屏幕截图
1.同时按下电源键+音量下键截屏 PhoneWindowManager.java private void interceptScreenshotChord() { if (mScreenshotCh ...
- 原生JavaScript拖动div兼容多种浏览器
说句题外话,虽然博客园嵌入式氛围不行,Web前端氛围还是很好的.我又从 chinaunix 回来了. <html> <head> <script type="t ...
- 服务器之间免密码ssh登陆
配置服务器f1(192.168.1.1)与服务器f2(192.168.1.2)之间免密码ssh登陆 一.首先,配置服务器主机名为f1.f2 1.更改/etc/sysconfig下的network文件, ...
- linux下安装python linux下一些常用的命令
注意 ubuntukylin-14.04.2-desktop-amd64 自带python2.7.6 这个说的比较详细 http://wenku.baidu.com/link?url=gaeFcQrc ...
- Redis 实现用户积分排行榜
排行榜功能是一个很普遍的需求.使用 Redis 中有序集合的特性来实现排行榜是又好又快的选择. 一般排行榜都是有实效性的,比如“用户积分榜”.如果没有实效性一直按照总榜来排,可能榜首总是几个老用户,对 ...
- mybatis 关联对象mapper.xml的写法
https://github.com/zfrHJ/mybaties/blob/master/mybaties/src/com/itheima/mybatits/mapper/OrdersMapperC ...
- Linux网络编程echo多线程服务器
echo_server服务器多线程版本 #include <unistd.h> #include <stdlib.h> #include <stdio.h> #in ...
- 用于A*的 二叉堆 AS3实现
package com.copper.isometric.pathing { import flash.sampler.startSampling; /** * ...