首页 > 其他分享 >线程

线程

时间:2022-11-27 17:25:59浏览次数:41  
标签:Console Thread state 线程 WriteLine new

线程和进程:

一个应用程序启动,会启动一个进程(应用程序运行的载体),然后进程启动多个线程。

使用Thread类创建和控制线程。

Thread thread = new Thread(Test);

thread.start();

class Program
    {
        public void Test()
        {
            Console.WriteLine("Test start....");
            Thread.Sleep(1000);
            Console.WriteLine("Test complet....");
        }
        
        static void Main(string[] args)
        {
            /*Program program = new Program();
            program.Test();*/
            Thread thread = new Thread(new Program().Test);//如果Test方法是静态的:Thread thread = new Thread(Test);
            thread.Start();
            Console.WriteLine("Main start....");
            Console.WriteLine("Main complet....");
        }
    }

获取线程id的方法:Thread.CurrentThread.ManagedThreadId

往线程里面去传递参数

使用thread.Start()可以传递无参的委托类型和有参的委托类型

传递一个数据:

static void DownLoad(Object obj)
{
    string str = obj as string; //使用as做类型转换,转换成功直接返回,转换不成功就会返回null.
    Console.WriteLine(str); 
}
static void Main(string[] args)
{
    Thread thread = new Thread(DownLoad);
    thread.Start("http://www.google.com/xx/xxx/xx.mp4"); //直接把该字符串传递给DownLoad方法。
    Console.WriteLine("Main complet...." + Thread.CurrentThread.ManagedThreadId); 
}

传递多个数据:

定义一个结构体:public struct Data{//定义需要传递的数据}

class Program
    {
        public struct Data  //结构体里声明需要传递的数据
        {
            public string name;
            public int age;
            public string massage;
        }
    
        static void DownLoad(Object obj)
        {
            Data data = (Data)obj;//结构体是值类型,不能使用as转换,只能使用强制转换
            Console.WriteLine("姓名:"+data.name+"年龄:"+data.age+"信息:"+data.massage);
        }
        
        static void Main(string[] args)
        {
            //定义需要传递的数据
            Data data = new Data();
            data.name = "张三";
            data.age = 12;
            data.massage = "new person";
            Thread thread = new Thread(DownLoad); 
            thread.Start(data); 
        }
    }

自定义类传递数据

后台线程和前台线程,一般用Thread创建的线程都是前台线程,后台线程操作:

var thread = new Thread(Test) {IsBackground = false}; //默认为前台线程(当主线程结束后,但子线程没有结束,会等所有的线程结束后该前台线程才结束)

var thread = new Thread(Test) {IsBackground = true}; //默认为后台线程(当主线程结束后,不论子线程结束与否,后台线程都会关闭)

线程的优先级

5个优先等级:Highest,AboveNormal,Normal,BelowNormal,Lowest

Thread a= new Thread(A);

a.Priority = ThreadPriority.Highest;

线程有5种状态:

新建(new Thread)、就绪(runnable),运行(running)、阻塞(blocked)、结束(dead)

线程池

线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防止过分调度。

从线程池中取出线程:ThreadPool.QueueUserWorkItem(Download);

 

1)线程池中的所有线程都是后台线程。如果进程的所有前台线程都结束了,所有的后台线程就会停止。不能把入池的线程改为前台线程;

2)不能给入池的线程设置优先级或者名称;

3)入池的线程只能用于时间较短的任务,如果线程要一直运行(如:word的拼写检查器线程),就应该使用Thread类创建一个线程。

任务

创建任务:

1)TaskFactory taskFactory = new TaskFactory();
   Task task = taskFactory.StartNew(Test);

2)Task task1 = new Task(Test);
      task1.Start();

连续任务:

task1.ContinueWith(Second);

static void First()
{
     Console.WriteLine("第一步");
     Thread.Sleep(2000);
}

static void Second(Task task)
{
      Console.WriteLine("第二步");
}

static void Main(string[] args)
{
      Task task1 = new Task(First);
      Task task2 = task1.ContinueWith(Second);
      task1.Start();
      Thread.Sleep(3000);
}

资源访问冲突

 class States
    {
       private int state = 5;
        public void StateChange()
        {
            if (state == 5)
            {
                state++;
                Console.WriteLine("state = :" + state + "   该线程为:" + Thread.CurrentThread.ManagedThreadId);
            }
            state = 5;
        }
    }
class Program
    {
        static void Main(string[] args)
        {
            States states = new States();
            for(int i = 0; i < 20; i++)
            {
                Thread thread = new Thread(states.StateChange);
                thread.Start();
            }
            
        }
    }
state = :6   该线程为:5
state = :5   该线程为:8
state = :5   该线程为:6
state = :6   该线程为:9
state = :6   该线程为:12
state = :6   该线程为:15

运行结果有些获得的状态为5,有的为6。原因是当某一线程执行到StateChange()方法中的打印语句行时,在它前面运行的线程已经执行将“state=5”语句执行完了,等于说state的值从5变成了6再次变成了5,因此,该线程打印出来的state=5。

使用锁机制可解决资源访问冲突。

锁的定义:private Object _lock = new Object();

锁的使用:锁只能被一个线程拿到,其他线程只能等待,锁使用完后,释放,其他线程抢占。

class States
    {
        private int state = 5;
        private Object _lock = new object();
        public void StateChange()
        {
            lock (_lock)
            {
                if (state == 5)
                {
                    state++;
                    Console.WriteLine("state = :" + state + "   该线程为:" + Thread.CurrentThread.ManagedThreadId);
                }
                state = 5;
            }
        }
    }

锁的好处:这段代码在同一时间只能被一个进程执行。

缺点:会拖慢多线程的执行速度。

多线程的死锁问题

有一把叉子和一把刀子,同时拿到叉子和刀子才能吃饭,

设计两个锁,分别对应叉子和刀子,

当线程拿了叉子的锁,同时也要拿刀子的锁才可以。否则会发生死锁:一个线程拿了叉子,去拿刀子时发现其他线程已经占用,则等待其他线程释放,而其他拿了刀子的线程也在等该线程释放叉子锁,两个线程都在等待对方释放锁。导致程序无法往下运行,造成死锁。

解决方法,设计取锁的先后顺序:先拿叉子再拿刀子

lock(_lock1){lock(_lock2){}}

class States
    {
        private int state1 = 5;
        private int state2 = 5;
        private Object _lock1 = new object();
        private Object _lock2 = new object();
        public void StateChange()
        {
            lock (_lock1)
            {
                Console.WriteLine("该线程为:" + Thread.CurrentThread.ManagedThreadId+"拿到了第1把锁");
                lock (_lock2)
                {
                    Console.WriteLine("该线程为:" + Thread.CurrentThread.ManagedThreadId + "拿到了第2把锁");
                    if (state1 == 5)
                    {
                        state1++;
                        Console.WriteLine("state = :" + state1 + "   该线程为:" + Thread.CurrentThread.ManagedThreadId);
                    }
                    state1 = 5;
                    if (state2 == 5)
                    {
                        state2++;
                        Console.WriteLine("state = :" + state2 + "   该线程为:" + Thread.CurrentThread.ManagedThreadId);
                    }
                    state2 = 5;
                }
            }
        }
    }

标签:Console,Thread,state,线程,WriteLine,new
From: https://www.cnblogs.com/Joyce-mi7/p/16922380.html

相关文章

  • C#的多线程机制探索1
    注:本文中出现的代码均在.netFrameworkRC3环境中运行通过一.多线程的概念Windows是一个多任务的系统,如果你使用的是windows2000及其以......
  • 浅谈C# Socket编程及C#如何使用多线程
    去年暑假学习了几个月asp.net最后几个星期弄了下C#socket.也算知道了个一知半解了,好久没动C#了,虽然这语言高级的让我对他没兴趣,不过还是回忆回忆,忘了一干二净就......
  • 今天将多线程的知识有回顾了下,总结了几点:
    新建一个线程(无参数,无返回值)Threadth=newThread(newpublicvoidPrintName()//函数{//函数体}这里一定注意ThreadStart中的函数是没有返回值和参数的那么......
  • c# 多线程
    usingusingusingusingnamespace{class{staticvoidMain(string[]args){"开始一个新的线程,名为次线程");newThread(newt.Start......
  • c#.net多线程编程教学(2):Thread类
    这章将向大家介绍.NET中的线程API,怎么样用C#创建线程,启动和停止线程,设置优先级和状态.在.NET中编写的程序将被自动的分配一个线程.让我们来看......
  • C#多线程点滴
     一、基本概念    进程:当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源。而一个进程又是由多个线程所组成的。    线程......
  • lambda表达式的引用多线程
    两种方式调用多线程(及lambda使用)publicvoidThread(){    //正常使用多线程    newThread(newRunnable(){      @Override    ......
  • Android 将函数放到主线程运行
    有时候,app会检测加密函数是否在主线程运行,为了逃避这种检测,要将函数放到主线程运行Class<?>aClass=RposedHelpers.findClass("com.yuanrenxue.challenge.three.Challen......
  • ORA-00742: 日志读取在线程 %d 序列 %d 块 %d 中检测到写入丢失情况----惜分飞
    标题:ORA-00742:日志读取在线程%d序列%d块%d中检测到写入丢失情况作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]由于......
  • java如何获取线程id呢?
    转自:​​http://www.java265.com/JavaCourse/202204/3183.html​​线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条......