多线程或不多线程!

时间:2011-01-19 16:28:06

标签: multithreading

这是个问题!

什么时候必须多线程应用程序,以及在多线程中一般要考虑什么?

如果一个例子与解释一起发布,我将不胜感激。

感谢。

PS。我在发帖前尝试检查所有可能的问题,如果这个问题只是另一个问题,请关闭它。

5 个答案:

答案 0 :(得分:13)

约瑟夫·阿尔巴海(Joseph Albahai)的Threading in C#有一个很好的章节 线程的使用和误用。它列出了线程的五个常见用例。

何时

维护自适应用户界面

  

通过运行耗时   并行“工作”线程上的任务,   主UI线程可以自由继续   处理键盘和鼠标事件。

有效利用原本阻止的CPU

  

多线程在线程时很有用   正在等待另一个人的回应   电脑或硬件。而   执行时阻止一个线程   任务,其他线程可以采取   否则没有负担的优势   计算机。

并行编程

  

执行密集的代码   计算可以更快地执行   多核或多处理器计算机   如果工作负载之间共享   一个多线程   “分而治之”战略

推测执行

  

在多核计算机上,您可以   有时可以提高性能   预测可能需要的东西   要做,然后提前做   时间LINQPad使用这种技术   加快新的创造   查询。一个变化是运行一个   中的不同算法的数量   并行,所有解决相同的任务。   无论哪一个完成   “胜利” - 这对你有用   不能提前知道哪个   算法将执行得最快。

允许同时处理请求

  

在服务器上,客户端请求可以   同时到达所以需要   并行处理(.NET   Framework为此创建线程   如果你使用ASP.NET,WCF,自动   Web服务或远程处理)。这个可以   也适用于客户(例如,   处理点对点网络 - 或   甚至来自用户的多个请求。)

何时不

他继续提醒读者

  

使用ASP.NET和ASP.NET等技术   WCF,你可能不知道   多线程甚至正在服用   place - 除非您访问共享数据   (可能是通过静态字段)没有   适当的锁定,运行冲突   线程安全。

     

线程也随之而来   附加条件。最大的是   多线程可以增加   复杂。有很多线程   本身并没有创造多少   复杂;这是互动   线程之间(通常通过共享   这样做的数据)。这适用于   或不是有意的互动,   并且可能导致长的开发周期   并且持续易受影响   间歇性和不可再生的错误。   出于这个原因,保留是值得的   互动到最低限度,到   坚持简单和成熟的设计   尽可能。本文   主要集中在处理公正问题上   这些复杂性;除掉   互动,并没有多少   说!

     

一个好的策略是   将多线程逻辑封装到   可以重用的类   独立检查和测试。   框架本身提供了许多   更高级别的线程构造,   我们稍后介绍。

     

线程也   导致资源和CPU成本   调度和切换线程(何时   有比活跃的线程更多   CPU核心) - 还有一个   创造/拆除成本。   多线程并不总是很快   你的应用程序 - 它甚至可以放慢速度   如果过度使用或降低它   不当。例如,何时   涉及重磁盘I / O,它可以   有几个工人更快   线程按顺序运行任务而不是   一次执行10个线程。   (在使用Wait和Pulse的信号中,我们   描述如何实现一个   生产者/消费者队列,其中   提供此功能。)

答案 1 :(得分:3)

多线程需要考虑许多方面。我推荐一个教程:来自Lesson: ConcurrencyJava Tutorial。然后你必须考虑表现,但这是一种特殊的能力。

当您面对其他问题时,您将了解其他问题。

答案 2 :(得分:2)

由于所有新一代CPU都具有多核架构,我真的建议开发ALWAYS多线程应用程序,以充分利用CPU的全部功能。

无论您使用何种语言,都不重要。当您接近多线程应用程序时,一般来说,您必须将软件视为两个或多个软件,并在其之间具有共享内存。

首先尝试找出可以并行化的软件部分。

例如,如果你有一个软件生成大量数据,然后你需要将它写在硬盘上,你可以考虑在两个线程中分割内存的生产者和内存的编写者。

在这种情况下,例如,你有第一个线程以FULL CPU速度生成数据,因为它可以创建数据,另一个线程以完全磁盘速度在磁盘上写入数据。

在这种情况下,您已经并行化了cpu以及在磁盘上写入数据的任务,并且最终会有一个更快的应用程序。 - 例如,将在第一个核心分配第一个线程。 - 第二个核心将分配第二个线程。

因此,由于磁盘速度较慢,因此您的PRODUCER线程上没有磁盘瓶颈。

我的2美分。

google this keyword:producer consumer algorithms

答案 3 :(得分:1)

  • 多线程是一个将流程分为多个概念的概念 独立子流程(称为线程),但它们可能依赖 在这种情况下,他们需要在单个资源上,例如数据资源 完全访问它。
  • 当我们希望处理器忙于某些时,需要线程 子进程(线程),而其他子进程正在等待IO或 任何其他资源。但是,线程只能在CPU上并行运行 是多核的,否则他们通常会分时工作 概念(一个子过程执行一段时间(时间量子)然后 其他)。

例如,我们可以通过在商店或MALL的计费柜台进行计费的过程来理解多线程。 因此,只有一个计数器是单线程进程,而多计数器是一个多线程进程。因此,在多线程中,整个计费过程被许多计费柜台(多个线程)划分为许多子流程,旨在进行计费工作。

因此,对于线程的实现,我们有以下示例:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;

namespace ThredsRND
{
    public abstract class TaskRequest
    {
    }
    public abstract class TaskManager<T> where T : TaskRequest
    {
        protected Queue<T> Requests = new Queue<T>();
        private int NumberOfThreads { get; set; }

        public void Run(int _numberOfThreads)
        {
            NumberOfThreads = _numberOfThreads;
            CreateTasks();
            List<Thread> threads = new List<Thread>();

            if (NumberOfThreads <= 0)
                NumberOfThreads = 1;

            for (int i = 0; i < NumberOfThreads; i++)
            {
                Thread th = new Thread(_ExecuteThread);
                th.Start();
                threads.Add(th);
            }

            threads.ForEach(x => x.Join());
        }

        private object _key = new object();

        private void _ExecuteThread()
        {
            while (true)
            {
                T request = null;
                lock (_key)
                {
                    if (Requests.Count > 0)
                        request = Requests.Dequeue();
                }

                if (request != null)
                {
                    Console.WriteLine("THREAD:" + Thread.CurrentThread.ManagedThreadId);
                    ExecuteTask(request);
                }
                else return;
            }
        }

        public abstract void CreateTasks();
        public abstract void ExecuteTask(T request);

    }
}

现在必须继承此taskManager类,并且需要定义其抽象函数。

例如:

 class SimpleReportRequest:TaskRequest
{
    public int Start { get; set; }
    public int End { get; set; }
}
class SimpleReportCreator : TaskManager<SimpleReportRequest>
{
    public override void CreateTasks()
    {
        for (int i = 1; i <= 100; i++)
        {
            SimpleReportRequest req = new SimpleReportRequest();
            req.Start = i;
            req.End = i+1;
            Requests.Enqueue(req);
        }
    }



public override void ExecuteTask(SimpleReportRequest request)
    {//what each process of this type should doo..  

}

主程序;

 static void Main(string[] args)
    {
        SimpleReportCreator creator = new SimpleReportCreator();
        DateTime start = DateTime.Now;
        Console.WriteLine("started at: "+ start);
        creator.Run(100);
        DateTime end = DateTime.Now;
        Console.WriteLine("Total Time taken with threads: " +(end-start));

        Console.WriteLine("ALL END");
        Console.ReadLine();

        return;}

希望这篇文章非常有用

答案 4 :(得分:0)

当我在应用程序中有很多不同类型的任务和优先级时,我使用多线程。

一个例子可能是,如果您需要将信息记录到数据库,但写入数据库需要太长时间并占用应用程序。如果您将日志记录放在另一个线程中,那么可以愉快地坐在那里运行查询而不需要与应用程序的其余部分进行交互。