读书人

开启20个线程往读取txt文件

发布时间: 2013-09-14 13:03:22 作者: rapoo

开启20个线程去读取txt文件
一个txt 大概有20W 行,我要把每行读取出来插入数据库,但是速度太慢,
如何开启20个线程去读取,然后插入数据库???
------解决方案--------------------




好吧 bs做多了,winform那确实了
不过其实也简单,考虑业务的时候忽视ui线程,完全就只做交互和显示用,不参与任何业务和运算逻辑。
只要是执行业务的 都封装一次,在后台线程里完成,那么对于后台线程来说,其实还是单线程的思路了。
[解决办法]
引用:
好吧 bs做多了,winform那确实了
不过其实也简单,考虑业务的时候忽视ui线程,完全就只做交互和显示用,不参与任何业务和运算逻辑。
只要是执行业务的 都封装一次,在后台线程里完成,那么对于后台线程来说,其实还是单线程的思路了。
多线程和UI没什么关系。。单线程的只是你自己的思想。。
[解决办法]
兄弟 20w 插入 很快的 秒内 都可以完成了 打包成list 然后分批 来批量插入
不要 一条条插入
[解决办法]
引用:
Quote: 引用:

好吧 bs做多了,winform那确实了
不过其实也简单,考虑业务的时候忽视ui线程,完全就只做交互和显示用,不参与任何业务和运算逻辑。
只要是执行业务的 都封装一次,在后台线程里完成,那么对于后台线程来说,其实还是单线程的思路了。
多线程和UI没什么关系。。单线程的只是你自己的思想。。

额 难道我的话没有表达出“多线程和UI没什么关系”这个论点么?
ui是交互线程,后台是工作线程,能把这两者分的比较清楚,就不会纠结什么多线程了。
[解决办法]
20万行应该不多啊
那就
string[] AllLine = File.ReadAllLine(@"c://1.txt");
Foreach(var item in AllLine){
Insert(item);


}



非得用多线程。。。
读的时候应该不可能 再说20万行数据不多File.ReadAllLine 一分钟足可以读出来了
写入。。。20万行也不多啊 你也可以开个线程 但是你要怎么管理?
开四个线程


测试文件 189MB
开启20个线程往读取txt文件

注:以下速度均经多次试验

单线程 3.5秒
开启20个线程往读取txt文件

2线程 2.0秒。。谁说多线程不能提高速度,这个响亮的嘴巴抽的你爽不?
开启20个线程往读取txt文件

3线程 3.08秒 速度略有降低
开启20个线程往读取txt文件

4线程 3.44秒 更慢
开启20个线程往读取txt文件

8线程 3.74秒 继续慢
开启20个线程往读取txt文件

16线程 3.46秒 这以后基本是单线程的速度了
开启20个线程往读取txt文件

至于这些现象表示了什么,原理是什么,自己研究吧。。。
[解决办法]
引用:


小伙挺猛 我其实就想知道你的文本文档如何让多个人同时访问的
难道是这个线程访问 锁死 读取 然后释放 解锁 其他线程锁死。。。这样?
不会吧 那和但线程有什么区别
[解决办法]

[解决办法]
引用:

仅仅是数据共享 没有锁的概念
[解决办法]
引用:



求私信 MP4文件读写库!大神 好久没见啊
[解决办法]

我喜欢这个表情
[解决办法]


测试文件 189MB
开启20个线程往读取txt文件

注:以下速度均经多次试验

单线程 3.5秒
开启20个线程往读取txt文件

2线程 2.0秒。。谁说多线程不能提高速度,这个响亮的嘴巴抽的你爽不?
开启20个线程往读取txt文件

3线程 3.08秒 速度略有降低
开启20个线程往读取txt文件

4线程 3.44秒 更慢
开启20个线程往读取txt文件

8线程 3.74秒 继续慢
开启20个线程往读取txt文件

16线程 3.46秒 这以后基本是单线程的速度了
开启20个线程往读取txt文件

至于这些现象表示了什么,原理是什么,自己研究吧。。。

我来汪两声。不废话,先上测试代码
        static void Main(string[] args)
{
fileThread fileThread = new fileThread(@"E:\data\WebSite\ShowJim.com.rar", @"e:\windows2003sql2000.GHO");
for (int threadCount = 1; threadCount != 10; ++threadCount) fileThread.WaitThread(threadCount);

Console.WriteLine("end...");
Console.ReadKey();
}
/// <summary>
/// 多线程文件读取测试
/// </summary>
private class fileThread
{
/// <summary>


/// 测试文件名
/// </summary>
private string fileName;
/// <summary>
/// 硬盘缓存刷新文件名,文件必须大于空闲内存数量
/// </summary>
private string memoryCacheFileName;
/// <summary>
/// 测试线程数量
/// </summary>
private int threadCount;
/// <summary>
/// 已完成线程数量
/// </summary>
private int finallyThreadCount;
/// <summary>
/// 测试文件数据缓冲区
/// </summary>
public byte[] Data { get; private set; }
/// <summary>
/// 多线程同步访问锁
/// </summary>
private readonly object threadLock = new object();
/// <summary>
/// 多线程文件读取测试
/// </summary>
/// <param name="fileName">测试文件名</param>
/// <param name="memoryCacheFileName">硬盘缓存刷新文件名,文件必须大于空闲内存数量</param>


public fileThread(string fileName, string memoryCacheFileName)
{
this.fileName = fileName;
this.memoryCacheFileName = memoryCacheFileName;
using (System.IO.FileStream file = System.IO.File.OpenRead(fileName)) Data = new byte[file.Length];
Console.WriteLine("测试文件: " + fileName + " 文件大小: " + Data.Length.ToString() + "B");
using (System.IO.FileStream file = System.IO.File.OpenRead(memoryCacheFileName))
{
Console.WriteLine("硬盘缓存刷新文件: " + memoryCacheFileName + " 文件大小: " + file.Length.ToString() + "B");
}
}
/// <summary>
/// 测试开始
/// </summary>
/// <param name="threadCount">测试线程数量</param>
public void WaitThread(int threadCount)
{
#region 硬盘缓存刷新
byte[] data = new byte[1 << 20];
using (System.IO.FileStream file = System.IO.File.OpenRead(memoryCacheFileName))
{
for (int count = (int)(file.Length / data.Length); count != 0; --count) file.Read(data, 0, data.Length);


}
#endregion

System.Diagnostics.Stopwatch time = new System.Diagnostics.Stopwatch();
time.Start();

this.threadCount = threadCount;
finallyThreadCount = 0;
while (threadCount != 0) new System.Threading.Thread(read).Start(threadCount--);
System.Threading.Monitor.Enter(threadLock);
System.Threading.Monitor.Wait(threadLock);
System.Threading.Monitor.Exit(threadLock);

time.Stop();
Console.WriteLine("测试线程数量: " + finallyThreadCount.ToString() + " 测试文件消耗时间: " + time.Elapsed.TotalSeconds.ToString() + "s");
}
/// <summary>
/// 读取文件线程处理
/// </summary>
/// <param name="threadNO">线程序号</param>
private void read(object threadNO)
{
int length = Data.Length / threadCount, thread = (int)threadNO, startIndex = (thread - 1) * length;
using (System.IO.FileStream file = System.IO.File.OpenRead(fileName))
{


file.Seek(startIndex, System.IO.SeekOrigin.Begin);
file.Read(Data, startIndex, thread == threadCount ? Data.Length - startIndex : length);
}
System.Threading.Monitor.Enter(threadLock);
if (++finallyThreadCount == threadCount) System.Threading.Monitor.Pulse(threadLock);
System.Threading.Monitor.Exit(threadLock);
}
}

再上测试结果,多次测试结果相差不大
 



其实不必和我纠结,我对这些东西不感兴趣,很久不玩编程了,没什么意思
[解决办法]
虚拟机配置:
开启20个线程往读取txt文件
[解决办法]

引用:
Quote: 引用:


求私信 MP4文件读写库!大神 好久没见啊
FileStream。。。。
[解决办法]
引用:
2.每次测试重启虚拟机

对于虚拟机有两点疑问:
1.虚拟机硬盘访问最终还是要访问宿主系统的硬盘缓存,启动虚拟机能否刷掉宿主系统的硬盘缓存要看空闲内存的大小、启动虚拟机读取量、虚拟机系统实际使用内存大小。
2.虚拟机访问硬盘是存在非硬盘访问阻塞因素的(源于虚拟机对于硬盘的文件的组织结构管理),影响类似于360流氓软件(当然影响没有那么严重)。当然随着虚拟机的流行,虚拟机测试也是一种应该考虑的情况,也许可以这样说:虚拟机中大文件的访问使用多线程能够提高效率。
[解决办法]
这事的瓶颈在于硬盘的性能上吧,无论你是几个线程,把硬盘读取速度撑满了事啊。
而硬盘读取速度又因为当前文件缓存,硬盘本身缓存使用,甚至文件内容本身所在磁道位置,而会有不同的速度曲线。

我觉得不同环境里面对多线程读取文件的测试结果会有不一样的结果,但是整体来说,读取速度一定不会超过某一上限,至于最快的是单线程还是多线程,和当前测试环境又有很大的关系。换句话说,你们这测试都是白干了啊!

最后回到楼主的问题,你这问题一点意义都没有。线程并不能显著提高文件读写性能,需要提高性能首先要知道性能的瓶颈在什么地方。
20w行文件读取的速度不会比20w行插入数据库更慢。

你的性能要提高顶多是弄个内存缓存区,读取插入各一个线程,文件读取后填入,插入那边只管缓存区是否有数据,这样整体速度取决于最慢的那一方了。

PS:眼镜兄今天火气很大啊!
引用:
Quote: 引用:
2.每次测试重启虚拟机

对于虚拟机有两点疑问:
1.虚拟机硬盘访问最终还是要访问宿主系统的硬盘缓存,启动虚拟机能否刷掉宿主系统的硬盘缓存要看空闲内存的大小、启动虚拟机读取量、虚拟机系统实际使用内存大小。
2.虚拟机访问硬盘是存在非硬盘访问阻塞因素的(源于虚拟机对于硬盘的文件的组织结构管理),影响类似于360流氓软件(当然影响没有那么严重)。当然随着虚拟机的流行,虚拟机测试也是一种应该考虑的情况,也许可以这样说:虚拟机中大文件的访问使用多线程能够提高效率。

[解决办法]
引用:
这事的瓶颈在于硬盘的性能上吧,无论你是几个线程,把硬盘读取速度撑满了事啊。
而硬盘读取速度又因为当前文件缓存,硬盘本身缓存使用,甚至文件内容本身所在磁道位置,而会有不同的速度曲线。

我觉得不同环境里面对多线程读取文件的测试结果会有不一样的结果,但是整体来说,读取速度一定不会超过某一上限,至于最快的是单线程还是多线程,和当前测试环境又有很大的关系。换句话说,你们这测试都是白干了啊!

最后回到楼主的问题,你这问题一点意义都没有。线程并不能显著提高文件读写性能,需要提高性能首先要知道性能的瓶颈在什么地方。
20w行文件读取的速度不会比20w行插入数据库更慢。

你的性能要提高顶多是弄个内存缓存区,读取插入各一个线程,文件读取后填入,插入那边只管缓存区是否有数据,这样整体速度取决于最慢的那一方了。
关键是硬盘读取速度并不是一个固定值,顺序读取与随机读取的速率至少相差2倍以上。虽然环境因素很重要,但是就单个线程而言应该尽量提高顺序读取的概率。即使并发存在其他硬盘操作,最坏情况也就是从顺序变成随机,而不应该自己默认制造随机。
上面的说法是基于干净的操作系统(没有安装类似360的硬盘读写监控流氓软件),也就是硬盘读写调用不会产生不可忽略的非硬盘操作阻塞行为。否则,多线程才可能提高读取速率,因为非硬盘阻塞可能导致单线程下硬盘不能接近于满负荷状态。

读书人网 >C#

热点推荐