美文网首页C#
面向对象(二十二)-多线程使用

面向对象(二十二)-多线程使用

作者: 元宇宙协会 | 来源:发表于2017-12-10 22:20 被阅读63次

1. Thread

Thread默认开启前台线程。 其他的开启方式默认开启后台线程。

  • 首先导入命名空间:
    System.Threading

  • 实例化一个Thread对象

Thread newThread = new Thread(AMethod);
 // AMethod,为该线程将要执行的任务。
  • 启动线程
    若要开始执行线程,可使用Start方法
    newThread.Start();
  • 停止线程
    newThread.Abort();

Thread线程的多种常用方法列表

方法 操作 雷潮
Start 使线程开始运行
Sleep 使线程暂停指定的一段时间。
Suspend 在线程到达安全点时,使其暂停。
Abort 在线程到达安全点时,使其停止。
Resume 重新启动挂起的线程
Join 使当前线程一直等到另一线程完成。 在与超时值一起使用时,如果该线程在分配的时间内完成,此方法将返回 True。

安全点:
安全点是指代码中公共语言运行时可以安全地执行自动“垃圾回收”的位置。垃圾回收是指释放不再使用的变量并回收内存的过程。 调用线程的 Abort 或 Suspend 方法时,公共语言运行时将对代码进行分析,确定让线程停止运行的适当位置。

属性 雷潮
IsAlive 如果线程处于活动状态,则包含值 True。
IsBackground 获取或设置一个布尔值,该值表示一个线程是否是,或是否应当是后台线程。 后台线程与前台线程类似,但后台线程不阻止进程停止。 一旦某个进程的所有前台线程都停止,公共语言运行时就会对仍处于活动状态的后台线程调用 Abort 方法,从而结束该进程。
Name 获取或设置线程的名称。 通常用于在调试时发现各个线程。
Priority 获取或设置操作系统用于确定线程调度优先顺序的值。
ApartmentState 获取或设置用于特定线程的线程模型。 线程模型在线程调用非托管代码时很重要。
ThreadState 包含描述线程状态的值。

Thread的相关属性:

属性 雷潮
IsAlive 如果线程处于活动状态,则包含值 True。
IsBackground 获取或设置一个布尔值,该值表示一个线程是否是,或是否应当是后台线程。 后台线程与前台线程类似,但后台线程不阻止进程停止。 一旦某个进程的所有前台线程都停止,公共语言运行时就会对仍处于活动状态的后台线程调用 Abort 方法,从而结束该进程。
Name 获取或设置线程的名称。 通常用于在调试时发现各个线程。
Priority 获取或设置操作系统用于确定线程调度优先顺序的值。
ApartmentState 获取或设置用于特定线程的线程模型。 线程模型在线程调用非托管代码时很重要。
ThreadState 包含描述线程状态的值。

线程优先级
每个线程都有一个优先级属性,用于确定其执行所占用的处理器时间片大小。 操作系统为高优先级线程分配较长的时间段,并为低优先级线程分配较短的时间段。 新创建的线程具有值Normal,但可以将 Priority 属性更改为 ThreadPriority 枚举中的任何值。

2. 通过委托来开启线程

通过委托,调用BeginInvoke方法来开启一条线程,去执行该委托所指向的方法。

// 线程执行该方法
        static string test1(int x, int y)
        {
            Console.WriteLine(x + y);
            return x + "+"+ y;
        }

        static void Main(string[] args)
        {

            Func<int, int, string> fun1 = test1;
            // 通过委托来开启线程执行。 倒数第二个参数是,线程执行完毕之后的回调方法, 倒数第一个参数是,执行完之后,携带的参数。
            fun1.BeginInvoke(10, 20, test1CallBack, fun1);
            
        }

        // 通过委托来传递回调函数,会自动将该线程的执行结果 传递过来
        static void test1CallBack(IAsyncResult ar)
        {
            //AsyncState 获取所携带的参数,在这里就是上面fun1.BeginInvoke(10, 20, test1CallBack, fun1); 这行代码中,所传递的fun1
            Func<int, int, string> fun1 = ar.AsyncState as Func<int, int, string>;
            // 获取委托所指向的方法的执行结果。
            string result =  fun1.EndInvoke(ar);
            Console.WriteLine("这就是结果" + result);
        }
// 模拟多线程场景
         static void Main(string[] args)
        {
            // 利用委托,注册下载图片方法       
            Func<int, int, string> f = DownLoadVideo;
            //f(10, 20);
       
            // 开启线程,并执行下载方法,下载完毕后,执行DownLoadIsOk方法
            f.BeginInvoke(10, 20,DownLoadIsOk,f);

            Console.ReadKey();
        }

        private static void DownLoadIsOk(IAsyncResult ar)
        {
            Console.WriteLine("视频已下载完毕");
            Console.WriteLine(ar.AsyncState);
        }

        private static string DownLoadVideo(int arg1, int arg2)
        {
            Console.WriteLine("正在下载视频");
            return arg1 + "" + arg2;
        }

3. 线程池

static void ThreadFunc3()
        {
            Console.WriteLine("--------");
            // 调用线程池来执行任务。 每调用一次,就会开启一条线程来执行该任务。
            ThreadPool.QueueUserWorkItem(test3);
            ThreadPool.QueueUserWorkItem(test3);
            ThreadPool.QueueUserWorkItem(test3);
            ThreadPool.QueueUserWorkItem(test3);
            ThreadPool.QueueUserWorkItem(test3);
            ThreadPool.QueueUserWorkItem(test3);
            ThreadPool.QueueUserWorkItem(test3);
            ThreadPool.QueueUserWorkItem(test3);
            Console.WriteLine("========");
            Thread.Sleep(100);
        }

        // 线程池调用的方法,需要一个object类型的参数方法,且不能有返回值
        static void test3(object obj)
        {
            Thread.CurrentThread.IsBackground = false;
            Console.WriteLine("asdas");
        }

4. Task 开启

static void ThreadMethod()
        {
            Console.WriteLine("ThreadMethod Begin" + Thread.CurrentThread.ManagedThreadId);
            Thread.Sleep(1000);
            Console.WriteLine("Thread End");
        }

        static void continueTask(Task t)
        {
            Console.WriteLine("task is continue" + t.Id);
            Thread.Sleep(3000);
            Console.WriteLine("task is complete");
        }

        static void Main(string[] args)
        {
            // 第一种方式开启
            //Task t = new  Task(ThreadMethod);
            //t.Start();

            //// 第二种方式开启
            //TaskFactory tf = new TaskFactory();
            //tf.StartNew(ThreadMethod);

            Task t1 = new Task(ThreadMethod);  
            Task t2 = t1.ContinueWith(continueTask);

            t1.Start(); // 开启任务 t1, 当t1执行完毕的时候,会执行t2的任务

            Console.ReadKey();
        }

5. 线程使用问题

  • 1、资源竞争
    多个线程访问同一个资源,对同一个资源做修改,会引发数据混乱。
  • 2、死锁
    多把锁。互相牵制。导致线程都互相等待解锁。
  • 3、案例:
  • 4、银行存取款
  • 5、多窗口同时卖票
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace TestProject
{
    class SaleTicket
    {
        private Thread thread1;
        private Thread thread2;
        private Thread thread3;
        private int ticketCount = 1000;

        public SaleTicket()
        {
            thread1 = new Thread(Sale);
            thread2 = new Thread(Sale);
            thread3 = new Thread(Sale);
        }

        public void Sale()
        {
            while(true)
            {
                lock(this)
                {
                    if (ticketCount > 0)
                    {
                        ticketCount -= 1;
                        Console.WriteLine(Thread.CurrentThread.Name + "卖了一张票,剩余" + ticketCount);
                    }
                    else
                    {
                        Console.WriteLine(Thread.CurrentThread.Name + ":票卖完了");
                        break;
                    }
                }
            }
        }

        public void StartSaleTicket()
        {
            thread1.Start();
            thread2.Start();
            thread3.Start();
        }
    }
}

作者:silence_k
链接:http://www.jianshu.com/p/00b33e5cd149
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

相关文章

网友评论

    本文标题:面向对象(二十二)-多线程使用

    本文链接:https://www.haomeiwen.com/subject/tccbixtx.html