多线程和单线程效率问题!

编程有钱人了 2015-07-15 01:56:59
承接上一个帖子
http://bbs.csdn.net/topics/391023458
针对我的提问很多人给出了方法,我随便试了一个,
不过上个帖子是我想多了,是我把问题想复杂了....
不过我还有一个问题就是,我用单线程测试的时间和多线测试的时间几乎差不多

private void Form1_Load(object sender, EventArgs e)
{

for (int i = 0; i < 10000; i++)
{
tasks[i] = "任务" + (i + 1);//加载模拟的任务 实际业务当中有很多代码 这里只是模拟
}
}
Stopwatch timer = new Stopwatch();//new一个stopwatch
string[] tasks = new string[10000];
private void button2_Click(object sender, EventArgs e)
{

timer.Start();//开始计算时间
//for (var i = 0; i < 12; i++)//注释了这句代码 就是单线程,但是执行的时间和多线程几乎一样,多次测试都是
new Thread(h => DoIt()).Start();
}

int index=0;
int ttindex=0;
private void DoIt()
{
while(true)
{
string task;
lock (tasks)
{
if (index >= tasks.Length) //所有任务都完成了
{
timer.Stop();//结束点,另外stopwatch还有Reset方法,可以重置。

Console.WriteLine(timer.Elapsed);//显示时间
Console.WriteLine(timer.ElapsedMilliseconds);// 显示到毫秒
break;
}
task = tasks[index++];
ttindex++;
Console.WriteLine("索引"+ttindex);
}
var tid = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine("正在执行{0}_线程id={1}", task, tid);
//Thread.Sleep(1); //随机阻塞一会儿
Console.WriteLine("{0}结束", task);
}
}

//for (var i = 0; i < 12; i++)//注释了这句代码 就是单线程,但是执行的时间和多线程几乎一样,多次测试都是

2:还有一个问题
我就一个普通的数组集合(DEMO就是上面的代码),很慢,因为实际业务中每循环一次 要大量计算等
现在想换成多线程加快速度,之前的帖子是我想复杂了,多线程只要不是两线程个同时处理某个任务就行,
但是要只要处理完就数字加1 要让进度条知道 处理了多少,至于多线程内部先处理哪个任务不重要,要的是当前处理了多少个


for (int i = 0; i < 10000; i++)
{
tasks[i] = "任务" + (i + 1);//加载模拟的任务 实际业务当中有很多代码 这里只是模拟
}

如上 用多线 处理就行,我感觉很简单,但是问题1中 发现 多线程和单线程用的时间几乎一样啊
...全文
655 23 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
runerback 2015-07-16
  • 打赏
  • 举报
回复

            string[] tasks = new string[1000];
            Parallel.For(0, 1000, i =>
            {
                tasks[i] = i.ToString();
            });
            Parallel.ForEach(tasks, task =>
            {
                Console.WriteLine("正在执行{0}个任务", task);
                Console.WriteLine("线程索引{0}", Thread.CurrentThread.ManagedThreadId);
                Thread.Sleep(new Random().Next(100));
            });
如果要求顺序不乱的话,要用第三个long参数,据说反而会降低速度,没试过
Poopaye 2015-07-15
  • 打赏
  • 举报
回复
引用 9 楼 wangjun8868 的回复:
[quote=引用 8 楼 shingoscar 的回复:] 大部分工作都在lock的范围内运行,WhiteLine也是互斥的,你这个算时间基本上就没有多线程的地方
求解决方案[/quote] 首先WriteLine肯定不是必要的,可以去掉 lock如果不是必要的,就应该去掉
足球中国 2015-07-15
  • 打赏
  • 举报
回复
典型的计算机基础根本就没学的人。
编程有钱人了 2015-07-15
  • 打赏
  • 举报
回复
引用 14 楼 shaoerbao 的回复:
lock不就用变回单线程了么。再说Parallel.For或ForEach才是真正意义上的多线程并行计算

 //声明线程数组
        string[] tasks = new string[1000];
        private void button2_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < 1000; i++)
            {
                tasks[i] = i.ToString();//加载模拟的任务 实际业务当中有很多代码 这里只是模拟
            }
            ParallelOptions d = new ParallelOptions();
            d.MaxDegreeOfParallelism = 24;
            System.Threading.Tasks.Parallel.ForEach(tasks,d, (index) => {  DoIt(index); });
        }
        int maxC = 0;
        private void DoIt(string i)
        {
            Console.WriteLine("正在执行{0}个任务",i);
            Console.WriteLine("索引{0}", maxC);
            maxC++;
            //Thread.Sleep(1);     //随机阻塞一会儿
        }
这样应该是我想要的,这样就是我想要的了,如果原生的办法 得写很多代码
WM_JAWIN 2015-07-15
  • 打赏
  • 举报
回复
你用单线种和多线程试一试,下载网站数据和读取本地文件试试。 你就会发现,多线程下载很快,读取文件跟单线程差不多,甚至更慢。
编程有钱人了 2015-07-15
  • 打赏
  • 举报
回复
引用 16 楼 xuzuning 的回复:
我在等 sp1234 的解释
你是版主 你 艾特 他
  • 打赏
  • 举报
回复
你这测试代码看着都这么费劲,子线程还弄个什么while(true) + lock,你就不能写点简单的代码作为子线程的逻辑,哪怕是你写个thread.sleep也行啊,你看看100个任务,用一个线程和多个线程的时间吧
xuzuning 2015-07-15
  • 打赏
  • 举报
回复
我在等 sp1234 的解释
编程有钱人了 2015-07-15
  • 打赏
  • 举报
回复
引用 14 楼 shaoerbao 的回复:
lock不就用变回单线程了么。再说Parallel.For或ForEach才是真正意义上的多线程并行计算
那我这个场景 如何编写?
编程有钱人了 2015-07-15
  • 打赏
  • 举报
回复
引用 12 楼 Z65443344 的回复:
你线程函数根本没有参数 假如你有100个数据需要处理 那么你循环开启10个线程,每个线程还是要处理1-100的数据,工作量反而加大了 而且你线程里的lock范围太大,把耗时的代码都同步处理了,这效率不变得更低已经算很好了
这100个任务不是线程自动分配的吗?如果不是那样,难道要开100个线程?如果我有100个任务 ,开10个线程去解决 如何写?
runerback 2015-07-15
  • 打赏
  • 举报
回复
lock不就用变回单线程了么。再说Parallel.For或ForEach才是真正意义上的多线程并行计算
於黾 2015-07-15
  • 打赏
  • 举报
回复
你线程函数根本没有参数 假如你有100个数据需要处理 那么你循环开启10个线程,每个线程还是要处理1-100的数据,工作量反而加大了 而且你线程里的lock范围太大,把耗时的代码都同步处理了,这效率不变得更低已经算很好了
编程有钱人了 2015-07-15
  • 打赏
  • 举报
回复
引用 10 楼 Forty2 的回复:
克服问题所在,不就是解决方案了? 如下代码并行时大概用1分钟,单线程用9分钟。
private void DoIt()
{
    while (true)
    {
        string task = null;
        lock (tasks)  // 锁里面尽量少做事情,保证不同线程拿到不同任务就可以了
        {
            if (index < tasks.Length)
            {
                task = tasks[index++];
            }
        }

        if (task == null)      //所有任务都完成了
        {
            timer.Stop();
            Console.WriteLine(timer.Elapsed);//显示时间
            Console.WriteLine(timer.ElapsedMilliseconds);
            break;
        }
        else
        {
            var tid = Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine("正在执行{0}_线程id={1}", task, tid);
            Thread.Sleep(50);     //耗时的工作要放到锁外面
            Console.WriteLine("{0}结束", task);
        }
    }
}
实际业务中 task = tasks[index++]; 这个task是参数,我要把这个参数传到一个方法中(这个方法会有大量计算的)

  private void DoIt()
        {
            while (true)
            {
                string task = null;
                lock (tasks)  // 锁里面尽量少做事情,保证不同线程拿到不同任务就可以了
                {
                    if (index < tasks.Length)
                    {
                        task = tasks[index++];
                        //加一个方法 
                        workCalute(task);//我要在这workCalute方法里干很多活  这样写可以吗?
                    }
                }

                if (task == null)      //所有任务都完成了
                {
                    timer.Stop();
                    Console.WriteLine(timer.Elapsed);//显示时间
                    Console.WriteLine(timer.ElapsedMilliseconds);
                    break;
                }
                else
                {
                    var tid = Thread.CurrentThread.ManagedThreadId;
                    Console.WriteLine("正在执行{0}_线程id={1}", task, tid);
                    Thread.Sleep(50);     //耗时的工作要放到锁外面
                    Console.WriteLine("{0}结束", task);
                }
            }
        }
Forty2 2015-07-15
  • 打赏
  • 举报
回复
克服问题所在,不就是解决方案了? 如下代码并行时大概用1分钟,单线程用9分钟。
private void DoIt()
{
    while (true)
    {
        string task = null;
        lock (tasks)  // 锁里面尽量少做事情,保证不同线程拿到不同任务就可以了
        {
            if (index < tasks.Length)
            {
                task = tasks[index++];
            }
        }

        if (task == null)      //所有任务都完成了
        {
            timer.Stop();
            Console.WriteLine(timer.Elapsed);//显示时间
            Console.WriteLine(timer.ElapsedMilliseconds);
            break;
        }
        else
        {
            var tid = Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine("正在执行{0}_线程id={1}", task, tid);
            Thread.Sleep(50);     //耗时的工作要放到锁外面
            Console.WriteLine("{0}结束", task);
        }
    }
}
编程有钱人了 2015-07-15
  • 打赏
  • 举报
回复
引用 8 楼 shingoscar 的回复:
大部分工作都在lock的范围内运行,WhiteLine也是互斥的,你这个算时间基本上就没有多线程的地方
求解决方案
Poopaye 2015-07-15
  • 打赏
  • 举报
回复
大部分工作都在lock的范围内运行,WhiteLine也是互斥的,你这个算时间基本上就没有多线程的地方
  • 打赏
  • 举报
回复
不是只有thread,而是BackgroundWorder, -》 不是只有一个thread,而是BackgroundWorder,
  • 打赏
  • 举报
回复
引用 2 楼 wangjun8868 的回复:
[quote=引用 1 楼 duanzi_peng 的回复:] 用简简单单的 for 循环 就下结论了???多线程是为了提高CPU利用率,减少耗时操作。至于效率问题,不放在具体的项目中 讨论,我个人感觉是没有依据的。
我不是那个意思,我说我的帖子中的代码 是不是写的以偶问题,两种方法时间差不多啊,有什么问题吗?上面的写法[/quote] 不是有没有问题,只是你这种测试方法有点 简单,也没有什么业务逻辑。 你这样,读取数据数据,搞一个2w行的,列数在10以上的表,在后台 分别用不同的线程方式去加载数据。另外 我所理解的 单线程 不是只有thread,而是BackgroundWorder, http://www.cnblogs.com/inforasc/archive/2009/10/12/1582110.html
编程有钱人了 2015-07-15
  • 打赏
  • 举报
回复
引用 4 楼 Forty2 的回复:
[quote=引用 楼主 wangjun8868 的回复:] lock (tasks) { if (index >= tasks.Length) //所有任务都完成了 { timer.Stop();//结束点,另外stopwatch还有Reset方法,可以重置。 Console.WriteLine(timer.Elapsed);//显示时间 Console.WriteLine(timer.ElapsedMilliseconds);// 显示到毫秒 break; } task = tasks[index++]; ttindex++; Console.WriteLine("索引"+ttindex); }
你的’工作‘都是在互斥锁的保护下运行的。 这已为着线程中的’工作‘要排队执行,怎么能快起来呢?[/quote] 如果不加LOCK 有可能两个不同的线程执行同一个业务
Forty2 2015-07-15
  • 打赏
  • 举报
回复
引用 楼主 wangjun8868 的回复:
lock (tasks) { if (index >= tasks.Length) //所有任务都完成了 { timer.Stop();//结束点,另外stopwatch还有Reset方法,可以重置。 Console.WriteLine(timer.Elapsed);//显示时间 Console.WriteLine(timer.ElapsedMilliseconds);// 显示到毫秒 break; } task = tasks[index++]; ttindex++; Console.WriteLine("索引"+ttindex); }
你的’工作‘都是在互斥锁的保护下运行的。 这已为着线程中的’工作‘要排队执行,怎么能快起来呢?
加载更多回复(3)

111,092

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧