【.Net】结合项目谈谈多线程
提到多线程, 大家都知道, 在进程中启用多个线程进行工作, 会提升程序的效率等等。
本篇文章旨在解释多线程的基础概念之外, 还要结合实际的项目来谈多线程的具体使用。
Thread
我们知道启动一个线程最直观的方法就是使用Thread类,f12看一下这个类的构造函数, 不多如下图:
使用thread要用两个参数, 一个是ThreadStart, 一个是ParameterizedThreadStart。这俩的区别是一个可以带参数一个可以不带参数, 如下面代码:
class demo1
{
public void test()
{
ThreadStart threadStart = new ThreadStart(Calculate);
Thread thread = new Thread(threadStart);
thread.Start();
} public void Calculate()
{
double Diameter = 0.5;
Console.Write("The perimeter Of Circle with a Diameter of {0} is {1}", Diameter, Diameter * Math.PI);
}
} public void test
{
ParameterizedThreadStart threadStart=new ParameterizedThreadStart(Calculate);
Thread thread=new Thread();
thread.Start(0.9);
} public void Calculate(object arg)
{
double Diameter=double(arg);
Console.Write("The perimeter Of Circle with a Diameter of {0} is {1}",
Diameter,Diameter*Math.PI);
}
ps: 这两个例子来源于网上。
实际项目中很多都是需要传递参数的情况。可以将需要的参数和线程执行的方法放到一个类中去, 调用的时候声明一个类的实例, 然后初始化属性, 方法执行时直接使用类中初始化好的属性来执行, 比如下面这个例子:
public class MyThread
{
public double Diameter = 10;
public double Result = 0; public MyThread(int Diameter)
{
this.Diameter = Diameter;
} public void Calculate()
{
Console.WriteLine("Calculate Start");
Thread.Sleep(2000);
Result = Diameter * Math.PI; ;
Console.WriteLine("Calculate End, Diameter is {0},Result is {1}", this.Diameter, Result);
}
} MyThread t=new MyThread(5.0);
ThreadStart threadStart=new ThreadStart(t.Calculate)
Thread thread=new Thread(threadStart);
thread.Start();
}
Ps:在不想写类的时候可以写个匿名函数代替, 这里对匿名函数不做赘述了。可以参考匿名函数
要注意的是匿名方法过长会造成程序可读性降低。
但是项目需求更多的是需要传递参数而且需要从线程调用完方法完毕后返回执行结果等。如果是多个子线程, 那么这里面涉及到的技术问题是如何保证线程同步。
线程池ThreadPool
线程池的使用是非常简单的,如下面的代码,把需要执行的代码提交到线程池,线程池内部会安排一个空闲的线程来执行你的代码,完全不用管理内部是如何进行线程调度的。
ThreadPool.QueqeUserWorkItem(t=>Console.WriteLine("Hello thread pool"));
每个CLR都有一个线程池,线程池在CLR内可以多个AppDomain共享,线程池是CLR内部管理的一个线程集合,初始是没有线程的,在需要的时候才会创建。线程池的主要结构图如下,基本流程如下:
1.线程池内部维护一个请求列队,用于缓存用户请求需要执行的代码任务,就是Thread.QueqeUserWorkItem提交的请求;
2.有新任务后,线程池使用空闲线程或者新线程来执行队列请求;
3.任务执行完后线程不会销毁,留着重复使用;
4.线程池自己负责维护线程的创建和销毁,但线程池有大量闲置的线程是,线程池会自动结束一部分多余的线程来释放资源;
线程池是有一个容量的,因为他是一个池子吗,可以设置线程池的最大活跃线程数,调用方法Threadpool.SetMaxThreads可是设置相关参数,但很多线程实践里都不建议程序猿们自己去设置这些参数,其实微软为了提高线程池性能,做了大量的优化,线程池可以很智能的确定是否要创建或者消费线程,大多数情况都可以满足需求了。线程池使得线程可以充分有效的被利用,减少了任务启动的延迟,也不用大量的去创建线程,避免了大量线程的创建和销毁对性能造成极大影响。
上面了解了线程的基本原理和诸多优点后,如果你是一个爱思考的猿类,应该会很容易的发现很多疑问,比如把任务添加到线程池队列后,怎么取消和挂起呢?如何知道他执行完了呢,下面来总结一下线程池的不足:
1.线程池内的线程不支持线程的挂起、取消等操作,如想要取消线程池的任务,.net支持一种协作方式取消,使用起来也不少很方便,而且有些场景并不是很满足需求;
2.线程内的任务没有返回值,也不知道何时执行完成;
3.不支持设置线程的优先级,还包括其他类似需要对线程有更多的控制的需求也不支持;
因此微软为我们提供了另外一个东西叫做Task来补充线程池的某些不足。
任务Task与并行Parallel
任务Task与并行Parallel本质上内部都是使用的线程池,提供了更丰富的并行编程的方式。任务Task基于线程池,可支持返回值,支持比较强大的任务执行计划定制等功能,下面实例。Task提供了很多方法和属性,通过这些方法和属性能够对Task的执行进行控制,并且能够获得其状态信息。Task的创建和执行都是独立的,因此可以对关联操作的执行拥有完全的控制权。
待续....
//创建一个任务
Task<int> t1 = new Task<int>(n =>
{
System.Threading.Thread.Sleep(1000);
return (int)n;
}, 1000);
//定制一个延续任务计划
t1.ContinueWith(task =>
{
Console.WriteLine("end" + t1.Result);
}, TaskContinuationOptions.AttachedToParent);
t1.Start();
//使用Task.Factory创建并启动一个任务
var t2 = System.Threading.Tasks.Task.Factory.StartNew(() =>
{
Console.WriteLine("t1:" + t1.Status);
});
Task.WaitAll();
Console.WriteLine(t1.Result);
并行Parallel内部其实使用的是Task对象(TPL会在内部创建Task的实例),所以的并行任务完成后才会返回。少量短时间任务建议就不要使用并行Parallel了,并行Parallel本身也是有性能开销的,而且还要进行并行任务调度、创建调用方法的委托等。
【.Net】结合项目谈谈多线程的更多相关文章
- Java实验项目四——多线程矩阵相乘算法的设计
Program:多线程矩阵相乘算法的设计 Description:利用多线程实现矩阵相乘,因为各个线程的运算互不影响, 所以不用使用锁,代码如下: thread.OperateMatrix类,实现矩阵 ...
- 开源项目实现多线程下载 (xutils)
public void download(View v){ EditText et_url = (EditText) findViewById(R.id.et_url); ...
- JAVA必背面试题和项目面试通关要点
一 数据库 1.常问数据库查询.修改(SQL查询包含筛选查询.聚合查询和链接查询和优化问题,手写SQL语句,例如四个球队比赛,用SQL显示所有比赛组合:举例2:选择重复项,然后去掉重复项:) 数据库里 ...
- JAVA JAVA面试题和项目面试核心要点精华总结(想进大公司必看)
http://blog.csdn.net/ourpush/article/details/53706524 1.常问数据库查询.修改(SQL查询包含筛选查询.聚合查询和链接查询和优化问题,手写SQL语 ...
- JAVA必背面试题和项目面试通关要点(带答案)
转载:https://blog.csdn.net/qq_36896779/article/details/78247050 一 数据库 1.常问数据库查询.修改(SQL查询包含筛选查询.聚合查询和链接 ...
- day9面向对象,多线程2
一.获取全部qq成员头像 import os,requests,pymongo class Qqgroup(object):#定义一个类 #定义获取QQ群的请求rul,抓包获取 group_rul = ...
- 多线程系列之 Java多线程的个人理解(一)
前言:多线程常常是程序员面试时会被问到的问题之一,也会被面试官用来衡量应聘者的编程思维和能力的重要参考指标:无论是在工作中还是在应对面试时,多线程都是一个绕不过去的话题.本文重点围绕多线程,借助Jav ...
- Java复习8.多线程
Java复习8 多线程知识 20131007 前言: 在Java中本身就是支持多线程程序的,而不是像C++那样,对于多线程的程序,需要调用操作系统的API 接口去实现多线程的程序,而Java是支持多线 ...
- iOS技术面试01:多线程与网络
1. 多线程的底层实现? 1> 首先搞清楚什么是线程.什么是多线程.多线程的使用场合(线程有时被称为轻量级进程,是程序执行流的最小单元.多线程是指软件或者硬件实现多个线程并发执行的技术.多线程的 ...
随机推荐
- 2017-2018-2 20165316 实验三《敏捷开发与XP实践》实验报告
2017-2018-2 20165316 实验三<敏捷开发与XP实践>实验报告 实验目的 安装 alibaba 插件,解决代码中的规范问题.再研究一下Code菜单,找出一项让自己感觉最好用 ...
- ActiveMQ任意文件写入漏洞(版本在5.12.X前CVE-2016-3088)
ActiveMQ任意文件写入漏洞(版本在5.12.X前CVE-2016-3088) 查看docker的activemq版本命令:$ docker ps | grep activemq927860512 ...
- rgferg
dfgsdfg fdvgdsafg fgdfgdfg
- 在Linux 中如何从进程相关的文件描述中恢复数据
在Linux中误删除了某个文件,但是 ps-ef|grep 文件名 发现某个进程还在使用该文件,那么可以通 过以下方式恢复文件. 例如:创建一个简单文件/tmp/test.txt, 随便向里面写点内容 ...
- JQuery ajax请求返回(parsererror)异常处理
目前在学习一个Java应用的框架,反编译后在执行时一直报错,界面上显示”parsererror”,经过JavaScript调试后发现更详细的错误提示信息是 Unexpected token ' in ...
- AJAX异步请求,局部刷新
AJAX异步请求,局部刷新 window.onload=function(){ //dom事件,页面加载完成执行如下函数 doGetObjects(); } function doGetObjects ...
- 【js】关于闭包和匿名函数
关于js闭包.之前我一直以为是匿名函数,以为封闭式的创建即执行销毁就是闭包,其实这是匿名函数,不一样的.也没有闭包的使用经验. 后来去网上查了下才知道,闭包的意思是:函数内部还有函数,返回一个函数,内 ...
- Linux学习笔记之Linux环境变量总结
0x00 概述 Linux是一个多用户多任务的操作系统,可以在Linux中为不同的用户设置不同的运行环境,具体做法是设置不同用户的环境变量. 0x01 Linux环境变量分类 按照生命周期来分,Lin ...
- 13: vue项目结构搭建与开发
vue其他篇 01: vue.js安装 02: vue.js常用指令 03: vuejs 事件.模板.过滤器 目录: 1.1 初始化项目 1.2 配置API接口,模拟后台数据 1.3 项目整体结构化开 ...
- RMAN入门——简介
RMAN(Recovery Manager) 1.简介 RMAN(Recovery Manager)是随Oracle服务器软件一同安装的工具软件,它可以用来备份和恢复数据库文件.归档日志和控制文件 ...