【转】细说.NET 中的多线程 (一 概念)

为什么使用多线程

 

1.使用户界面能够及时响应用户的输入

当某个应用程序在进行大量运算时候,为了保证应用程序能够随时响应客户的输入,这个时候我们往往需要让大量运算和响应用户输入这两个行为在不同的线程中进行。

2.效率原因

应用程序经常需要等待一些资源,如等待网络资源,等待io资源,等待用户输入等等。这种情况下使用多线程可以避免CPU长时间处于闲置状态。

3.多线程的性能损耗

1)用户态、内核态切换性能损耗
线程内的资源有两种运行态,即用户态和内核态。某些运算可以在堆栈上进行,这种情况线程是在用户态运行的。如果需要运行一些高权限的指令,或者某些优先级很高的指令需要在操作系统内核中进行,这个时候线程会运行在内核态。出于安全原因,用户态和内核态的资源是不能够互相访问的,因此在用户态和内核态的切换过程中,我们需要进行相关上下文以及变量的复制,这意味的用户态和内核态的切换是以一定的时间消耗为代价的。

2)进程上下文切换损耗
由于CPU是以时间片为单位进行线程切换,并且CPU的运算速度远大于内存的读写速度,因此CPU和内存之间通常有两级缓存,不同的线程的上下文访问的数据往往是不同的,这样线程的切换需要经常频繁的切换CPU缓存的内容,也需要更新线程的调度信息,这些都是需要花费一定的时间的,因此合理的使用多线程,来避免CPU不停的进行上下文切换。

System.Thread介绍

创建一个线程

创建每一个线程的时候,CLR都需要进行一系列的操作,如初始化线程的本地资源,为线程分配用户模式和内核模式下相应的堆栈,加载相应的托管,非托管资源等。

最简单常用的创建线程的方式是使用ThreadStart来创建线程,相关代码如下:

ThreadStart只需要一个委托即可,如果你善于使用匿名方法,也可以用匿名方法来代替委托,使用匿名方法的另一个好处是可以通过匿名方法的闭包特性来为新的线程传递参数。

虽然使用匿名方法的闭包特性可以很方便的为线程传递参数,但是也往往会带来一些不容易发现的问题,如下面的程序,由于i变量的共享,在运行的时候输出会有问题:

正确的写法应该是这样的:

线程异常的捕获

如果线程中可能需要捕获异常,那么我们不能这样做:

而是这样做:

System.Thread线程的成员

System.Threading.Thread帮助我们实现了一些线程的基本操作,如:

属性名称

说明

CurrentContext

获取线程正在其中执行的当前上下文。

CurrentThread

获取当前正在运行的线程。

ExecutionContext

获取一个 ExecutionContext 对象,该对象包含有关当前线程的各种上下文的信息。

IsAlive

获取一个值,该值指示当前线程的执行状态。

IsBackground

获取或设置一个值,该值指示某个线程是否为后台线程。

IsThreadPoolThread

获取一个值,该值指示线程是否属于托管线程池。

ManagedThreadId

获取当前托管线程的唯一标识符。

Name

获取或设置线程的名称。

Priority

获取或设置一个值,该值指示线程的调度优先级。

ThreadState

获取一个值,该值包含当前线程的状态。

 

 

方法名称

说明

Abort()    

终止本线程。

GetDomain()

返回当前线程正在其中运行的当前域。

GetDomainId()

返回当前线程正在其中运行的当前域Id。

Interrupt()

中断处于 WaitSleepJoin 线程状态的线程。

Join()

已重载。阻塞调用线程,直到某个线程终止时为止。

Resume()

继续运行已挂起的线程。

Start()  

执行本线程。

Suspend()

挂起当前线程,如果当前线程已属于挂起状态则此不起作用

Sleep()  

把正在运行的线程挂起一段时间。

 

前台线程vs后台线程

这里我们单独提一下前台线程和后台线程。在CLR中,线程分为前台线程和后台线程,当所有前台的线程执行完之后,CLR会强制结束所有正在运行的后台线程,并且不会出现任何异常。

因此你应该使用前台线程来做一些必须完成的任务,比如把流从内存中写到磁盘上。后台线程可以做一些不那么重要的事情。一旦线程对象的生命周期开始,你就不能修改IsBackground值。

 

由于线程是非常昂贵的资源,我们经常需要控制允许多少线程同时运行,如何控制线程的生命周期,如何管理线程,这里我们引入了线程池的概念。

 

细说.NET中的多线程 (二 线程池)

 


作者:独上高楼
出处:http://www.cnblogs.com/myprogram/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/436760.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【转】细说.NET中的多线程 (二 线程池)

上一章我们了解到,由于线程的创建,销毁都是需要耗费大量资源和时间的,开发者应该非常节约的使用线程资源。最好的办法是使用线程池,线程池能够避免当前进程中大量的线程导致操作系统不停的进行线程切换,当线程数量到达…

java第二章_零基础学Java第二章

一、第一个代码案例1.1. HelloWorld案例1.1.1 代码执行流程我们写的代码都将以.java开头的文件保存,经过类编译器编译成.class的字节码文件,然后通过解释器翻译与机器交流1.1.1 代码执行流程1. 编写代码步骤首先定义一个类:public class 类名…

java volidate_volidate 学习

一:Volatile 变量具有synchronized的可见性,有序性 特性,但是不具备原子特性二:java memory model(jmm) java 内存模型形象理解见下图Java Memory Modela:java 线程读取共享内存变量流程:线程2 --> JMM …

【转】ABP源码分析一:整体项目结构及目录

ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序。 整个Abp的Infrastructure是以Abp这个package为核心模块(core)15个模块(module).其中13个依赖于Abp这个核心包。另外两个包(FluentMigration,Web.Resources)相对独…

【转】ABP源码分析二:ABP中配置的注册和初始化

一般来说,ASP.NET Web应用程序的第一个执行的方法是Global.asax下定义的Start方法。执行这个方法前HttpApplication 实例必须存在,也就是说其构造函数必然已完成了执行。 ABP开始的地方就是HttpApplication的构造函数。 如下图一,Abp定义了一…

【转】ABP源码分析三:ABP Module

Abp是基于模块化设计思想进行构建的。开发人员可以将自定义的功能以模块(module)的形式集成到ABP中。具体的功能都可以设计成一个单独的Module。Abp底层框架提供便捷的方法集成每个Module.下图是所有Abp自带的module.AbpModule是所有Module的基类&#x…

java weka 聚类_简单开源数据挖掘工具weka进行文本聚类

目前非代码的数据挖掘工具很多,但非开源,weka是一款开源软件。只要安装jdk环境就可使用(具体安装jdk可以百度)本文将论述如何不用代码,使用weka操作,通过与文档频数与单词权的特征选择方法进行文本聚类(数据为附件)第一步&#xf…

java 不识别enum_Java enum关键字不识别的快速解决办法

从别人那儿拷贝过来的myeclipse java工程,打开一看标红了一大片,仔细一看,原来是不识别enum关键字,这就有点尴尬了。我自己重新建了一个java工程,测试了下,假如我在新建工程的时候选择javase-1.6&#xff1…

【转】ABP源码分析四:Configuration

核心模块的配置 Configuration是ABP中设计比较巧妙的地方。其通过AbpStartupConfiguration,Castle的依赖注入,Dictionary对象和扩展方法很巧妙的实现了配置中心化。配置中心化是一个支持模块开发的框架必备功能。 ABP中核心功能模块中的一些功能的运行时…

【转】ABP源码分析五:ABP初始化全过程

ABP在初始化阶段做了哪些操作,前面的四篇文章大致描述了一下。 为个更清楚的描述其脉络,做了张流程图以辅助说明。其中每一步都涉及很多细节,难以在一张图中全部表现出来。每一步的细节(会涉及到较多接口,类&#xff0…

【转】ABP源码分析六:依赖注入的实现

ABP的依赖注入的实现有一个本质两个途径:1.本质上是依赖于Castle这个老牌依赖注入的框架。2.一种实现途径是通过实现IConventionalDependencyRegistrar的实例定义注入的约定(规则),然后通过IocManager来读取这个规则完成依赖注入。…

【转】ABP源码分析七:Setting 以及 Mail

本文主要说明Setting的实现以及Mail这个功能模块如何使用Setting. 首先区分一下ABP中的Setting和Configuration。 Setting一般用于需要通过外部配置文件(或数据库)设置的简单类型数据(一般就是字符串),比如SMTP HOST.…

【转】ABP源码分析八:Logger集成

ABP使用Castle日志记录工具,并且可以使用不同的日志类库,比如:Log4Net, NLog, Serilog... 等等。对于所有的日志类库,Castle提供了一个通用的接口来实现,我们可以很方便的处理各种特殊的日志库,而且当业务需…

java并发锁获取的方式_Java精通并发-notify方法详解及线程获取锁的方式分析

wait():在上一次https://www.cnblogs.com/webor2006/p/11404521.html中对于无参数的wait()方法的javadoc进行了解读,而它是调用了一个参数的重载方法,回忆下:其中如果传0代表无限等待,否则是等待指定的时间就会停止等待…

【转】ABP源码分析九:后台工作任务

文主要说明ABP中后台工作者模块(BackgroundWorker)的实现方式,和后台工作模块(BackgroundJob)。ABP通过BackgroundWorkerManager来管理BackgroundJobManager,然后通过BackgroundJobManager来管理Background…

【转】ABP源码分析十:Unit Of Work

ABP以AOP的方式实现UnitOfWork功能。通过UnitOfWorkRegistrar将UnitOfWorkInterceptor在某个类被注册到IOCContainner的时候,一并添加到该类在容器中对应的ComponentModel的Interceptors集合中。总结一句话就是,UOW的功能是通过自定义Castle拦截器来实现…

【转】ABP源码分析十一:Timing

Timing这个简单实用的功能主要用来以统一的方式表示时间。因为ABP中有大量的module,另外还支持自定义module,所以将时间统一表示为local时间(默认)或utc时间是必要的。 IClockProvider:提供获取当前时间和标准化时间的接口。 UtcClockProvide…

【转】ABP源码分析十二:本地化

本文逐个分析ABP中涉及到localization的接口和类,以及他们之间的关系。本地化主要涉及两个方面:一个是语言(Language)的管理,这部分相对简单。另一个是语言对应得本地化资源(Localization)的管理…

【转】ABP源码分析十三:缓存Cache实现

ABP中有两种cache的实现方式:MemoryCache 和 RedisCache. 如下图,两者都继承自ICache接口(准确说是CacheBase抽象类)。ABP核心模块封装了MemoryCache 来实现ABP中的默认缓存功能。 Abp.RedisCache这个模块封装RedisCache来实现缓存…

java 酒店预定 app_Android应用源码酒店在线预定app项目全套

【实例简介】Android应用源码酒店在线预定app项目全套【实例截图】【核心代码】package com.bn.summer;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;…