IT知识库 购物 网址 游戏 小说 歌词 快照 开发 股票 美女 新闻 笑话 | 汉字 软件 日历 阅读 下载 图书馆 编程 China
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
vbs/VBScript DOS/BAT hta htc python perl 游戏相关 VBA 远程脚本 ColdFusion ruby专题 autoit seraphzone PowerShell linux shell Lua Golang Erlang 其它教程 CSS/HTML/Xhtml html5 CSS XML/XSLT Dreamweaver教程 经验交流 开发者乐园 Android开发资料
站长资讯 .NET新手 ASP.NET C# WinForm Silverlight WCF CLR WPF XNA VisualStudio ASP.NET-MVC .NET控件开发 EntityFramework WinRT-Metro Java C++ PHP Delphi Python Ruby C语言 Erlang Go Swift Scala R语言 Verilog 其它语言 架构设计 面向对象 设计模式 领域驱动 Html-Css JavaScript jQuery HTML5 SharePoint GIS技术 SAP OracleERP DynamicsCRM K2 BPM 信息安全 企业信息 Android开发 iOS开发 WindowsPhone WindowsMobile 其他手机 敏捷开发 项目管理 软件工程 SQLServer Oracle MySQL NoSQL 其它数据库 Windows7 WindowsServer Linux
  IT知识库 -> .NET新手区 -> 多线程编程学习笔记 -> 正文阅读

[.NET新手区]多线程编程学习笔记

多线程编程学习笔记 接上文 多线程编程学习笔记-基础(一) 接上文 多线程编程学习笔记-基础(二) 九、向线程传递参数
 1.代码如下。

using System;

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; //引入线程
using System.Diagnostics;
 

namespace ThreadConsoleApp
{

    class Program
    {
        static void Main(string[] args)
        {

            Console.WriteLine("开始,给线程传参数");          

            var fore = new ThreadBackground(10);   

            Thread t = new Thread(fore.CountNumber);
            t.Name = "线程1";         

            //启动线程

            t.Start();
            t.Join();
            Console.WriteLine("----------------------------"); 

            var t2 = new Thread(Count);
            t2.Name = "线程2";
            t2.Start(8);
            t2.Join();
            Console.WriteLine("----------------------------"); 

            var t3 = new Thread(()=>CountNumber(12));
            t3.Name = "线程3";
            t3.Start();
            t3.Join();
            Console.WriteLine("----------------------------");

 

            int i = 10;
            var t4 = new Thread(() => PrintNumber(i));
            t4.Name = "线程4";
            i = 20;
            var t5 = new Thread(() => PrintNumber(i));
            t5.Name = "线程5";
            t4.Start();
            t5.Start();
            Console.Read();
        }

        static void CountNumber(int cnt)
        {
            for (int i = 0; i < cnt; i++)
            {

                Thread.Sleep(500);
                Console.WriteLine(string.Format(" {0}    打印 {1,11} 数字", Thread.CurrentThread.Name, i.ToString("N0")));

            }

        }

        static void Count(object cnt)
        {
            CountNumber((int)cnt);
        }
        static void PrintNumber(int num)
        {        

            Console.WriteLine(string.Format(" {0} 打印 {1,11} 数字", Thread.CurrentThread.Name, num.ToString("N0")));         

        } 
    }
}

 

 2.结果如下图。
 

线程1,我们通过实例化对象来进行参数传递。
线程2,我们使用Thread.Start()来传递参数,不过此方法只接收单个参数,而且是对象类型。
线程3,我们使用lambda表达式进行参数传递,lambda表达式定义了一个不属于任何类的方法,同时该方法调用了我们实际要执行的方法,同时传递参数给线程。
线程4与线程5,则是显示了使用lambda表达式进行参数传递的一个问题,即当多个lambda表达式共用一个变量时,它们会共享这个变量的值。如图中线程4与线程5所显示,没有打印10,只打印了20。
十、使用lock锁定操作
 1.代码如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; //引入线程
using System.Diagnostics;
 

namespace ThreadConsoleApp
{
    class Program
    {

        static void Main(string[] args)
        {
            Console.WriteLine("开始,给线程加锁");           

            var c = new Counter();           

            Thread t = new Thread(()=>Count(c));
            var t3 = new Thread(() => Count(c));

             var t2 = new Thread(() => Count(c));
            t.Name = "线程1";         

            //启动线程
            t.Start();
         

            t2.Name = "线程2";
            t2.Start();     
 
            t3.Name = "线程3";
            t3.Start();
            t.Join();
            t2.Join();     
            t3.Join();
            Console.WriteLine(string.Format("没有加锁的多线程总计:{0}",c.Count));
            Console.WriteLine("----------------------------");


            var c1 = new CounterLock();
            var t4 = new Thread(() => Count(c1));
            t4.Name = "线程4";
           

            var t5 = new Thread(() => Count(c1));
            t5.Name = "线程5";
            var t6 = new Thread(() => Count(c1));
            t6.Name = "线程6";

            t4.Start();
            t5.Start();
            t6.Start();
            t4.Join();
            t5.Join();
            t6.Join();
            Console.WriteLine(string.Format("加锁的多线程总计:{0}", c1.Count));
            Console.Read();
        }      

        static void Count(CountBase cnt)
        {
            for (int i = 0; i < 100000; i++)
            {
                cnt.Incerement();
                cnt.Dncerement();

            }
        }
     }

    abstract class CountBase
    {
         public abstract void  Incerement();
        public abstract void Dncerement();
    }

    class Counter : CountBase
    {
        public int Count { get; private set; }
        public override void Dncerement()
        {
            Count--;
        }

        public override void Incerement()
        {

            Count++;
        }
    }

    class CounterLock : CountBase
    {
        private readonly object objSync = new object();
        public int Count { get; private set; }
        public override void Dncerement()
        {
            lock (objSync)
            {
                Count--;
            }       
        }

        public override void Incerement()
        {
            lock (objSync)
            {
                Count++;
            }
        }
    }

}

 

2. 结果如下图
 

      主线程首先创建了一个 Counter的实例对象,这个类定义了一个可以增,可以 减的简单计数器。然后我们创建了三个线程,这三个线程共享一个Counter对象。由于没有对共享变量的锁定,所以在一个周期内,对共享变量的改变,在上个线程没结束之前,当前线程又对共享变量进行了操作,我们会得到不同的计数值,如上图所示。为了防止这种情况的发生,所以我们要对共享变量进行加锁。使用lock关键字锁定对象,这样在一个线程操作完成之前,其他线程都不能对共享变量进行操作。
十一、Moniter对资源的锁定
 1.代码如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; //引入线程
using System.Diagnostics; 

namespace ThreadConsoleApp
{   
 class Program
    {
        static void Main(string[] args)
        {

            Console.WriteLine("开始,线程死锁");          

            var lock1 = new object();
            var lock2 = new object();
           

            Thread t = new Thread(()=> DeadLock(lock1,lock2));
            t.Name = "线程1";       

            //启动线程

            t.Start();
            lock (lock2)
            {
                Thread.Sleep(2000); 

                if (Monitor.TryEnter(lock1,TimeSpan.FromSeconds(5)))

                {
                    Console.WriteLine("在规定时间内,请求资源");

                }
                else

                {
                    Console.WriteLine("超时,无法获取资源");

                }
            }

            new Thread(() => DeadLock(lock1, lock2)).Start();
             Console.WriteLine("-----------------------------");

            lock (lock2)
            {

                Thread.Sleep(1000);
                Console.WriteLine(string.Format("死锁线程"));

               lock(lock1)
                {
                    Console.WriteLine("请求资源成功");

                }          
           }

            Console.Read();
        }
      

        /// <summary>
        /// 死锁方法
        /// </summary>
        /// <param name="objLock1"></param>
        /// <param name="objLock2"></param>
        static void DeadLock(object objLock1,object objLock2)
        {
            lock (objLock1)
            {
                Thread.Sleep(2000);
                lock (objLock2)
                {
                    Console.WriteLine("死锁");
                }
            }
        }
    }
}

2.结果如下图
 

 先看deadlock方法,这个方法先锁定lock1对象,然后等待2秒之后,锁定了lock2对象。然后在子线程中启动了这个方法。
主线程中先锁定了lock2对象,然后等待获取lock1对象。由于子线程锁定了lock1对象,等待lock2对象。所以造成了死锁。
十二、多线程的异常处理
 1.代码如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; //引入线程
using System.Diagnostics;
 
namespace ThreadConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {

            Console.WriteLine("开始,异常处理");          
            Thread t = new Thread(FaultyThread);
            t.Name = "线程1";        

            //启动线程
            t.Start();
            t.Join();
            try
            {
                t = new Thread(ExpectThread);
                t.Start();
            }

            catch (Exception ex)
            {
                Console.WriteLine("异常信息:" + ex.Message);
            }
            Console.Read();
        }    

        static void ExpectThread()
        {
            Console.WriteLine(string.Format("异常处理"));
            Thread.Sleep(2000);
            throw new Exception("抛出异常");
        }
        static void FaultyThread()
        {
            try
            {
                Console.WriteLine(string.Format("异常处理2"));
                Thread.Sleep(1000);
                throw new Exception("抛出异常2");
            }

            catch (Exception ex)
            {
                Console.WriteLine(string.Format("异常处理2:{0}",ex.Message));
            }        

        }
    }
}

 2.结果如下图。
 

 在程序中定义了两个处理异常的方法,一个对异常进行了处理,另一个没有对异常进行处理。最后如图。程序崩溃了。
上一篇文章      下一篇文章      查看所有文章
加:2017-10-25 23:21:37  更:2017-10-25 23:21:46 
 
  .NET新手区 最新文章
将ZIP文件添加到程序集资源文件然后在运行时
Web服务的调用
.NET创建WebService服务简单的例子
多线程编程学习笔记——任务并行库(三)
序列化和反序列化
Spring学习之路
cs代码实现控件移动TranslateTransform
Asp.net基础知识
ACdream原创群赛(11)の风神日华神专场C.神奇
SQL 存储和触发器
技术频道: 站长资讯 .NET新手区 ASP.NET C# WinForm Silverlight WCF CLR WPF XNA Visual Studio ASP.NET MVC .NET控件开发 Entity Framework WinRT/Metro Java C++ PHP Delphi Python Ruby C语言 Erlang Go Swift Scala R语言 Verilog 其它语言 架构设计 面向对象 设计模式 领域驱动设计 Html/Css JavaScript jQuery HTML5 SharePoint GIS技术 SAP Oracle ERP Dynamics CRM K2 BPM 信息安全 企业信息化其他 Android开发 iOS开发 Windows Phone Windows Mobile 其他手机开发 敏捷开发 项目与团队管理 软件工程其他 SQL Server Oracle MySQL NoSQL 其它数据库 Windows 7 Windows Server Linux
脚本语言: vbs/VBScript DOS/BAT hta htc python perl 游戏相关 VBA 远程脚本 ColdFusion ruby专题 autoit seraphzone PowerShell linux shell Lua Golang Erlang 其它教程
网站开发: CSS/HTML/Xhtml html5 CSS XML/XSLT Dreamweaver教程 经验交流 开发者乐园 Android开发资料
360图书馆 软件开发资料 文字转语音 购物精选 软件下载 新闻资讯 小游戏 Chinese Culture 股票 三丰软件 开发 中国文化 网文精选 阅读网 看图 日历 万年历 2018年10日历
2018-10-24 3:17:57
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT知识库