文档章节

要出去找工作了,复习下多线程吧

开源中国123456789
 开源中国123456789
发布于 2017/05/08 17:35
字数 1888
阅读 33
收藏 0
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace TheardDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            var objMessage = new Message();

            #region 无参多线程,  基于ThreadStart委托

            // 摘要:
            //     表示在 System.Threading.Thread 上执行的方法。
            //[ComVisible(true)]
            //public delegate void ThreadStart();
            var threadStart = new ThreadStart(objMessage.ShowMessage);
            var thread1 = new Thread(threadStart); //Thread重构两个构造方法,  一个是无参的ThreadStart委托
            thread1.Start(); //默认为前端线程(必须等待所有)

            #endregion

            #region 有参数多线程,  基于ParameterizedThreadStart委托

            // 摘要:
            //     表示在 System.Threading.Thread 上执行的方法。
            //
            // 参数:
            //   obj:
            //     包含该线程过程的数据的对象。
            //[ComVisible(false)]
            //public delegate void ParameterizedThreadStart(object obj);
            var person = new Person
            {
                Name = "paul",
                Age = 12
            };

            var parameterizedThreadStart = new ParameterizedThreadStart(objMessage.ShowMessage); //此委托只接收object的参数
            var thread2 = new Thread(parameterizedThreadStart)
            {
                IsBackground = true //指示某个线程是否为后台线程。
            };
            thread2.Start(person);

            #endregion

            Console.Read();
        }
    }

    public class Message
    {
        public void ShowMessage()
        {
            var message = string.Format("线程唯一标识 : {0},", Thread.CurrentThread.ManagedThreadId);
            Console.WriteLine("{0}要出去找工作了, 看看多线程", message);
            for (var i = 0; i < 100; i++)
            {
                Thread.Sleep(100);
                Console.WriteLine(i);
            }
        }

        public void ShowMessage(object person)
        {
            var objPerson = (Person) person;
            var message = string.Format("线程唯一标识 : {0},", Thread.CurrentThread.ManagedThreadId);
            Console.WriteLine("{0}姓名:{1},年龄:{2}要出去找工作了, 看看多线程", message, objPerson.Name, objPerson.Age);
            for (var i = 0; i < 100; i++)
            {
                Thread.Sleep(100);
                Console.WriteLine(i);
            }
        }
    }

    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
}

其中线程Start()默认为前台线程, 就拿一般应用程序来说,一定要等待所有线程里的内容执行完成才可以回车关闭窗口, 但是如果把IsBackground = true , 即使线程调用的方法中的内容没执行完,你回车就会结束所有线程,包括主线程, MSDN解释如下:

线程是后台线程或前台线程。 后台线程均与前台线程相同,只不过后台线程不会阻止进程终止。 属于某个进程的所有前台线程已都终止,公共语言运行时结束该进程。 任何剩余的后台线程已停止,并不会完成。 默认情况下,以下线程执行在前台 (即,其IsBackground属性返回false): 主线程 (或主应用程序线程)。 通过调用创建的所有线程Thread类构造函数。 默认情况下,以下线程在后台执行 (即,其IsBackground属性返回true):

挂起线程Thread.Join 即使将线程设置了后台线程, 但是我们还是希望他能全部执行完再结束所有线程,所以就用到了挂起线程Thread.Join 方法

var person = new Person
            {
                Name = "paul",
                Age = 12
            };

            var parameterizedThreadStart = new ParameterizedThreadStart(objMessage.ShowMessage); //此委托只接收object的参数
            var thread2 = new Thread(parameterizedThreadStart)
            {
                IsBackground = true //指示某个线程是否为后台线程。
            };
            thread2.Start(person);
            thread2.Join();//在继续执行标准的 COM 和 SendMessage 消息泵处理期间,阻止调用线程,直到由该实例表示的线程终止。
       

终止线程Thread.Abort

 var person = new Person
            {
                Name = "paul",
                Age = 12
            };

            var parameterizedThreadStart = new ParameterizedThreadStart(objMessage.ShowMessage); //此委托只接收object的参数
            var thread2 = new Thread(parameterizedThreadStart)
            {
                IsBackground = true //指示某个线程是否为后台线程。
            };
            thread2.Start(person);
            thread2.Join(); 



public void ShowMessage(object person)
        {
            try
            {
                var objPerson = (Person) person;
                var message = string.Format("线程唯一标识 : {0},", Thread.CurrentThread.ManagedThreadId);
                Console.WriteLine("{0}姓名:{1},年龄:{2}要出去找工作了, 看看多线程", message, objPerson.Name, objPerson.Age);
                for (var i = 0; i < 100; i++)
                { 
                    if (i == 10)
                    {
                        Thread.CurrentThread.Abort(i);
                    }
                    Console.WriteLine(i);
                }
            }
            catch (ThreadAbortException e)
            {
                Thread.ResetAbort();
            }
            Console.WriteLine("2222222222222222222222");
        }

MSDN解释: 当调用 Abort 终止线程,则系统引发 ThreadAbortException。 ThreadAbortException 是一个特殊的异常可被捕捉的应用程序代码,但将被重新引发在 catch 块的结尾处除非 ResetAbort 调用。 ResetAbort 取消请求中止,并防止 ThreadAbortException 终止该线程。

输入图片说明]

如果不用Thread.ResetAbort();

public void ShowMessage(object person)
       {
           try
           {
               var objPerson = (Person) person;
               var message = string.Format("线程唯一标识 : {0},", Thread.CurrentThread.ManagedThreadId);
               Console.WriteLine("{0}姓名:{1},年龄:{2}要出去找工作了, 看看多线程", message, objPerson.Name, objPerson.Age);
               for (var i = 0; i < 100; i++)
               { 
                   if (i == 10)
                   {
                       Thread.CurrentThread.Abort(i);
                   }
                   Console.WriteLine(i);
               }
           }
           catch (ThreadAbortException e)
           {
                //此处不做任何处理
           }
           Console.WriteLine("2222222222222222222222");
       }

输入图片说明

**CLR线程池 ThreadPool ** 使用ThreadStart与ParameterizedThreadStart建立新线程非常简单,但通过此方法建立的线程难于管理,若建立过多的线程反而会影响系统的性能。 有见及此,.NET引入CLR线程池这个概念。CLR线程池并不会在CLR初始化的时候立刻建立线程,而是在应用程序要创建线程来执行任务时,线程池才初始化一个线程。线程的初始化与其他的线程一样。在完成任务以后,该线程不会自行销毁,而是以挂起的状态返回到线程池。直到应用程序再次向线程池发出请求时,线程池里挂起的线程就会再度激活执行任务。这样既节省了建立线程所造成的性能损耗,也可以让多个任务反复重用同一线程,从而在应用程序生存期内节约大量开销。 CLR线程池所建立的线程总是默认为后台线程,优先级数为ThreadPriority.Normal。 CLR线程池分为工作者线程(workerThreads)与I/O线程 (completionPortThreads) 两种,工作者线程是主要用作管理CLR内部对象的运作,I/O(Input/Output) 线程顾名思义是用于与外部系统交换信息

MSDN解释: 托管线程池中的线程为后台线程, 即它们的 IsBackground 属性为 true。 这意味着在所有的前台线程都已退出后,ThreadPool 线程不会让应用程序保持运行。 也可以将与等待操作不相关的工作项排列到线程池。 若要请求由线程池中的一个线程来处理工作项,请调用 QueueUserWorkItem 方法。 此方法将对将被从线程池中选定的线程调用的方法或委托的引用用作参数。 一个工作项排入队列后就无法再取消它。 计时器队列中的计时器以及已注册的等待操作也使用线程池。 它们的回调函数也会排列到线程池。 每个进程都有一个线程池。 从 .NET Framework 4 版开始,进程的线程池的默认大小由虚拟地址空间的大小等多个因素决定。 进程可以调用 GetMaxThreads 方法以确定线程的数量。 使用 SetMaxThreads 方法可以更改线程池中的线程数。 每个线程使用默认的堆栈大小并按照默认的优先级运行。

//把CLR线程池的最大值设置为1000
            ThreadPool.SetMaxThreads(1000, 1000);
            //显示主线程启动时线程池信息
            ThreadMessage("Start");
            //启动工作者线程
            ThreadPool.QueueUserWorkItem(new WaitCallback(objMessage.ThreadCallback)); 
            int workerThreads;
            int portThreads;
            ThreadPool.GetAvailableThreads(out workerThreads,
                out portThreads);
            Console.WriteLine("\n可用工作线程: \t{0}" +
                              "\n可用完成端口线程: {1}\n",
                workerThreads, portThreads);
            Console.Read();

ThreadPool.QueueUserWorkItem(new WaitCallback(objMessage.ThreadCallback));里面的回调是一个WaitCallback委托,参数类型是object的, 如果ThreadPool.QueueUserWorkItem(new WaitCallback(objMessage.ThreadCallback));如果在后面没有显示的传入参数将直接传入null

// 摘要:
    //     表示线程池线程要执行的回调方法。
    //
    // 参数:
    //   state:
    //     包含回调方法要使用的信息的对象。
    [ComVisible(true)]
    public delegate void WaitCallback(object state);

我们常常要查看线程是还有多少可以使用就可以使用ThreadPool.GetAvailableThreads

int workerThreads;
          int portThreads;
          ThreadPool.GetAvailableThreads(out workerThreads,
              out portThreads);
          Console.WriteLine("\n可用工作线程: \t{0}" +
                            "\n可用完成端口线程: {1}\n",
              workerThreads, portThreads);

不过线程的话还需要加一点就是锁, lock所以或者是Monitor 类进行处理

大致就这样了, 要出去找工作了复习复习

© 著作权归作者所有

开源中国123456789
粉丝 6
博文 77
码字总数 66184
作品 0
海淀
私信 提问
做项目servlet和框架选哪个?

现在大四了,准备找工作了,想找java方面的。这学期还有个课程设计 我打算用java做一个我们学校的就业信息系统。现在发愁的是用不用框架,还是单纯的用servlet+jdbc,以前自己写东西,包括给...

luger
2012/09/06
2K
4
java新手求助,好心人

java代码敲的不熟,也没有项目经验,出去找工作没人爱要,能给些建议么?大家们, 我会的东西 java基础(面向对象、数组、I/O、Socket、多线程、servlet、jsp) java数据结构(数组、链表、栈、...

询问java1
2014/08/10
426
14
Python学到什么程度才可以去找工作?掌握这4点足够了!

大家在学习Python的时候,有人会问“Python要学到什么程度才能出去找工作”,对于在Python培训机构学习Python的同学来说这都不是问题,因为按照Python课程大纲来,一般都不会有什么问题,而对...

p柯西
2018/06/27
211
0
【深圳/广州】求职第二天

最近忙在着工作,每天面试完回家都要把面试中的面试点巩固和知识复习,导致文章更新较慢,见谅。 【正文】 从前一天到UC面试完了之后,立马搭高铁来到了深圳。 来的路上电话和OSC里面的一个素...

大米被占用
2013/11/21
1K
14
【杂谈】我学习这么好,为什么找不到工作?

很多学生直到求职,都没有对自己的职业有一个明确的规划。 去年参加阿里巴巴产品经理的实习招聘,面试的时候有一个兄弟,可能是浙大的硕士,他的简历上没有什么和互联网相关的经历,但是他有...

qq_39521554
2018/04/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

PostgreSQL 11.3 locking

rudi
今天
5
0
Mybatis Plus sql注入器

一、继承AbstractMethod /** * @author beth * @data 2019-10-23 20:39 */public class DeleteAllMethod extends AbstractMethod { @Override public MappedStatement injectMap......

一个yuanbeth
今天
13
1
一次写shell脚本的经历记录——特殊字符惹的祸

本文首发于微信公众号“我的小碗汤”,扫码文末二维码即可关注,欢迎一起交流! redis在容器化的过程中,涉及到纵向扩pod实例cpu、内存以及redis实例的maxmemory值,statefulset管理的pod需要...

码农实战
今天
4
0
为什么阿里巴巴Java开发手册中不建议在循环体中使用+进行字符串拼接?

之前在阅读《阿里巴巴Java开发手册》时,发现有一条是关于循环体中字符串拼接的建议,具体内容如下: 那么我们首先来用例子来看看在循环体中用 + 或者用 StringBuilder 进行字符串拼接的效率...

武培轩
今天
9
0
队列-链式(c/c++实现)

队列是在线性表功能稍作修改形成的,在生活中排队是不能插队的吧,先排队先得到对待,慢来得排在最后面,这样来就形成了”先进先出“的队列。作用就是通过伟大的程序员来实现算法解决现实生活...

白客C
今天
87
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部