多线程系列(二):多线程基础

目录

  • 线程的几种状态
  • 基础线程
  • 前台线程、后台线程
  • 线程池概念理解

一、线程的几种状态

我们所说的基础线程就是通过Thread类显示创建的线程。可以大体了解一下Thread类相关的成员:

属性:

方法:

线程的5个状态:

1、       创建状态(new): 对应 Thread th= new Thread(worker) 时 ,就创建了一个新的线程,仅仅是新建状态,程序还没有运行线程中的代码~

2、就绪状态(Runnable):  对应 th.Start()方法,新建线程在接收到Start()命令之后,调用Run()方法,具体的执行线程。

* 虽然调用了Start()方法,但是线程也不一定即时运行Run()方法。我们知道,多线程是CPU在线程之间来回切换,给出一种多线程的感觉。

      如果资源紧张,线程较多,有可能在切换到当前这个线程前,需要等待一段时间。当CPU切换到当前这个线程时,在给定的时间片内运行我们的线程。

3、运行状态(Running):  在切换到当前线程时,在CPU给定的时间片内,真正的运行线程。

4、  阻塞状态(Blocked):  对应 Join()、Sleep()方法。阻塞状态是当前运行线程,暂时中断运行,让出CUP时间片,使得其他正在等待Run()的线程可以真正Run()。

<1> Join()方法:将调用Join()方法的线程,加入到当前线程。使得当前线程挂起,一直到调用Join()方法线程执行完毕。 

static void Main(string[] args)
{
            System.Threading.Thread childThead = new System.Threading.Thread(ChildThread);

            childThead.Start();

            //childThead.Join();

            Console.WriteLine("Main thread is end");

            Console.ReadKey();
        }

        static void ChildThread()
        {
            System.Threading.Thread.Sleep(10000);
            Console.WriteLine("ChildThread is end");
}

先显示主线程的信息,大约10s后,子线程信息显示,运行结果:

我们解开注释:childThead.Join();  这里需要理解的是,是将子线程childThead加入到主线程中,主线程挂起,直到子线程childThread执行完毕后,主线程才被唤醒,继续执行。

我们想让谁优先执行,就让我们希望的线程调用Join().所以以上执行的结果是,首先显示子线程信息,完毕后,主线程才显示信息。

<2>Sleep()方法:使得当前线程休眠挂起相应的毫秒数,到了一定的时间就会唤醒自己,继续执行。这里休眠的毫秒数不一定是经过这个时间点就马上唤醒,因为CPU需要在线程间来回切换。

  Thread.Sleep(0);在我们遇到长时间运行的线程时,执行一下,会让CPU根据优先级对线程重新排队选择。也许会是当前这个线程,或许是优先级更高的。

<3>Suspend()这个方法不建议使用。

5、   死亡状态(Dead): 对应 Abort()方法。让线程进入死亡状态有两种方式:<1>程序结束后,线程自然就会结束。<2>执行中,抛出异常。

   Abort(),就是让线程抛出异常来终止线程。 

二、基础线程

1、创建线程

常用有2种方式可以让我们显示创建一个线程

public Thread(ThreadStart start);
public Thread(ParameterizedThreadStart start);

参数:ThreadStart(无参无返回值委托) 和 ParameterizedThreadStart(有一个参数无返回值委托)  就是一个委托,如下:

public delegate void ThreadStart();
public delegate void ParameterizedThreadStart(object obj);

先创建一个与之(此例为:ThreadStart委托)对应的方法:

static void ChildThread()
{
            System.Threading.Thread.Sleep(10000);
            Console.WriteLine("ChildThread is end");
}

再创建基础线程:

System.Threading.Thread childThead = new System.Threading.Thread(ChildThread);

childThead.Start();

三、前台线程与后台线程

CLR将线程分为两种,即前台线程和后台线程。

线程的状态可以从前台和后台,在生命周期中来回切换。

应用程序主线程以及通过Thread对象显示创建的线程默认为前台线程,线程池的线程默认为后线程。

实例:

System.Threading.Thread backgroundThread = new System.Threading.Thread(BackGroundThreadWorker);

            if (!backgroundThread.IsBackground)
                backgroundThread.IsBackground = true;

            backgroundThread.Start();           

            var mt = System.Threading.Thread.CurrentThread;

            mt.Name = "Main";

            Console.WriteLine("【Main Thread】: Name—{0};IsBackground—{1};ThreadState—{2}", mt.Name, mt.IsBackground.ToString(), mt.ThreadState.ToString());

            Console.WriteLine("Main thread end.");

            Console.WriteLine();

            //主线程没有结束,后台线程继续运行~~
            //Console.ReadKey();

与子线程委托对应的方法

public static void BackGroundThreadWorker()
{
            var bc = System.Threading.Thread.CurrentThread;

            bc.Name = "Background";

            Console.WriteLine();

            Console.WriteLine("【Background Thread】:Name—{0};IsBackground—{1};ThreadState—{2}", bc.Name, bc.IsBackground.ToString(), bc.ThreadState.ToString());

            System.Threading.Thread.Sleep(10000);

            Console.WriteLine("Background thread end.");
}

<1>我们运行以上程序,发现主线程(前台线程)的信息显示后,程序直接结束,后台线程也就结束,所以不显示信息。

<2>解开以下注释,使得主线程在等待,所以大约10s后,子线程信息显示。

//主线程没有结束,后台线程继续运行~~
            Console.ReadKey();

四、线程池概念理解

前面讲过,线程池中的线程是后台线程。

为什么会有线程池? 因为创建线程和销毁线程相对来说需要消耗大量的时间和资源。 太多的线程会浪费内存,操作系统需要在线程间来回切换,线程过多,有损性能。

线程池就是一个可持续性发展的线程集合,线程池内部维护着一个消息队列,当一条方法名引用追加到线程池的队列中,线程池会提取当前项,派发给线程池中空闲的线程。 有以下几种情况: 如果线程池中没有线程,就创建一个线程。

如果并发的请求数过多,且请求速度超出线程池处理速度,就会创建额外线程。

如果线程完成任务,不会销毁,会进入空闲状态,等待下个请求的响应。

如果在一定的时间内没有接收到请求,超度空闲,就会自己醒来,终止自己,释放资源。

~~~~~~~~  续集~~~~~~~

时间: 2024-10-11 11:21:43

多线程系列(二):多线程基础的相关文章

多线程系列(1)多线程基础和Thread

因为现项目中有用到多线程和并发的知识,所以打算近期补习一下多线程相关的内容.第一篇文章从最基础的开始,就是如何开启一个线程,如何启动线程和阻塞线程等,这篇文章分以下几点进行总结. 多线程初印象 多线程的使用场景 线程的启动,挂起和终止 一个简单的多线程实例 多线程初印象 首先通过一张图来了解一下进程Process,应用程序域AppDomain和线程Thread之间的关系. 从图中可以总结出以下几点: 一个进程Process可能包含多个应用程序域,也包含多个线程,线程也可以穿梭于多个应用程序域当中

[.net 面向对象程序设计进阶] (17) 多线程(Multithreading)(二) 多线程高级应用

[.net 面向对象程序设计进阶] (17) 多线程(Multithreading)(二) 多线程高级应用 本节要点: 上节介绍了多线程的基本使用方法和基本应用示例,本节深入介绍.NET多线程中的高级应用. 主要有在线程资源共享中的线程安全和线程冲突的解决方案:多线程同步,使用线程锁和线程通知实现线程同步. 1. ThreadStatic特性 特性:[ThreadStatic] 功能:指定静态字段在不同线程中拥有不同的值 在此之前,我们先看一个多线程的示例: 我们定义一个静态字段: static

java多线程系列(二)

对象变量的并发访问 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我的理解能让知识更加简单易懂. 目录 认识cpu.核心与线程 java多线程系列(一)之java多线程技能 java多线程系列(二)之对象变量的并发访问 java多线程系列(三)之等待通知机制 java多线程系列(四)之ReentrantLock的使用 线程安全 线程安全就是多线程访问时,采用了加锁机制,当一个

c# 多线程系列二 自定义线程执行器

看了第一篇文章,多线程系列,看到了在线程执行任务队列有了一定的了解~! 那么今天我来讲讲,怎么样构建通用的自定义线程概念! 线程执行任务,肯定要有目标,但是如果写死了,那么一个线程处理执行职能按照思路处理一类任务,显然不满足我们的实际场景的需求,那么怎么才能创建灵活的线程执行器呢! 首先我们来创建一个任务构造器! 1 /// <summary> 2 /// 线程模型执行任务 基类 3 /// </summary> 4 public abstract class BaseTask 5

带你玩转java多线程系列 二 Thread 和 Runnable

Thread 和 Runnable 1 Runnable是接口,而Thread是继承,可以同时实现多个接口,但是不能同时继承多个类 2 Runnable比Thread灵活的多 当我们使用Runnable测试多线程非常简单,因为Runnable是对Thread的进一步解耦 我们首先建立一个类记做为Model,实现Runnable接口,在类里建立一个实例变量,接着覆盖run方法. 我们重新建立一个含有main函数的类,在该类中我们首先建立一个Model类型的实例变量model,接着将该Runnabl

Java多线程系列二——Thread类的方法

Thread实现Runnable接口并实现了大量实用的方法 public static native void yield(); 此方法释放CPU,但并不释放已获得的锁,其它就绪的线程将可能得到执行机会,它自己也有可能再次得到执行机会 public static native void sleep(long millis) throws InterruptedException; 此方法释放CPU,但并不释放已获得的锁,其它就绪的线程将得到执行机会,在休眠时间结束后,当前线程继续执行 publi

Java 多线程系列2——多线程的生命周期及生产消费者模型

一.线程的生命周期及五种基本状态 关于Java中线程的生命周期,首先看一下下面这张较为经典的图: 上图中基本上囊括了Java中多线程各重要知识点.掌握了上图中的各知识点,Java中的多线程也就基本上掌握了.主要包括: Java线程具有五中基本状态 新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread(); 就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态.处于就绪状态的线程,只是说

Java多线程系列

参考资料: http://www.jianshu.com/p/40d4c7aebd66 0.环境 Java: jdk1.8.0_91 CPU: Intel Core i5-6500 Memory: 8G 1.说明 本系列文章为Java多线程的学习记录 Java多线程系列一--Java实现线程方法 Java多线程系列二--Thread类的方法 Java多线程系列三--实现线程同步的方法 Java多线程系列四--控制线程执行顺序 Java多线程系列五--列表类 Java多线程系列六--Map实现类

MySQL并发复制系列二:多线程复制 2016

并发复制(Parallel Replication) 系列二: Enhanced Multi-threaded Slaves作者:沃趣科技MySQL数据库工程师  麻鹏飞 首先梳理下传统MySQL/MariaDB主备复制基本原理: 主从复制通过三个线程来完成,在master节点运行的binlog dump的线程,I/O线程和SQL线程运行在slave 节点 master节点的Binlog dump线程,当slave节点与master正常连接的时候,master把更新的binlog 内容推送到sl