C#学习记录-线程

线程

定义:Thread t = new Thread(Test);   //可以用匿名  lamda

调用:t.Start("ljc6666");方法可以无参或一个参数,如果要传入多个参数,可以传入一个结构体

namespace _17_线程Thread
{
    internal class Program
    {
        static void Test()
        {
            Console.WriteLine("1");
            Thread.Sleep(3000);//子线程等3s
            Console.WriteLine("2");
        }

        struct Data
        {
            public int Value;
            public int Value2;
        }


        static void show(object o)
        {
            Data op = (Data)o;
            Console.WriteLine("给我什么打印什么:"+ op.Value + op.Value2.ToString());
        }

        delegate void TestDelegate();
        static void Main(string[] args)
        {
            //Thread t = new Thread(Test);
            //t.Start();
            //Thread.Sleep(1000);//主线程等1s
            //Console.WriteLine("3");

            //Thread t = new Thread(() => Console.WriteLine("拉姆达表达式线程,线程id为:"+Thread.CurrentThread.ManagedThreadId));
            //t.Start();

            //Thread t = new Thread(delegate ()
            //{
            //    Console.WriteLine("匿名表达式线程,线程id为:" + Thread.CurrentThread.ManagedThreadId);
            //});
            //t.Start();

            //Console.WriteLine("主线程,线程id为:" + Thread.CurrentThread.ManagedThreadId);

            Data data = new Data();
            data.Value = 1;
            data.Value2 = 2;

            Thread t = new Thread(show);
            //t.Start("ljc6666");

            t.Start(data);

        }
    }
}

前后台线程

只有一个前台线程在运行,应用程序的进程就在运行,如果多个前台线程在运行,但是Main
方法结束了,应用程序的进程仍然是运行的,直到所有的前台线程完成其任务为止。
在默认情况下,用Thread类创建的线程是前台线程。线程池中的线程总是后台线程。
在用Thread类创建线程的时候,可以设置IsBackground属性,表示它是一个前台线程还是一
个后台线程
namespace _18_前台后台线程
{
    internal class Program
    {

        static void Test()
        {
            Console.WriteLine(Thread.CurrentThread.Name+"线程开启");
            Thread.Sleep(1000);
            Console.WriteLine(Thread.CurrentThread.Name+"线程结束");
        }

        static void Main(string[] args)
        {
            Thread thread = new Thread(Test);
            thread.IsBackground = true;   //设置为后台线程
            //thread.IsBackground = false;    //设置为前台线程
            thread.Start();
            Console.WriteLine("主线程结束");
        }
    }
}

线程优先顺序以及状态

在Thead类中,可以设置Priority属性,以影响线程的基本优先级 ,Priority属性是一个
ThreadPriority枚举定义的一个值。定义的级别有Highest ,AboveNormal,Normal,BelowNormal 和 Lowest。
需要注意的是,并不是优先级高的执行完了才会执行低的;
另外,下面这个程序由于CPU都很充足,不能很好的体现优先级顺序
如果需要等待线程的结束,可以调用Thread对象的Join方法,表示把Thread加入进来,停
止当前线程,并把它设置为WaitSleepJoin状态,直到加入的线程完成为止。
namespace _19_线程优先级和状态
{
    internal class A
    {
        
    }

    internal class Program
    {
        static void A()
        {
            int i = 0;
            bool flag = true;
            while (flag)
            {
                i++;
                Console.Write("a:"+i+" ");
                if (i>200000 )
                    flag = false;
            }
        }
        static void B()
        {
            int i = 0;
            bool flag = true;
            while (flag)
            {
                i++;
                Console.Write("b:" + i + " ");
                if (i > 200000)
                    flag = false;
            }
        }
        static void C()
        {
            int i = 0;
            bool flag = true;
            while (flag)
            {
                i++;
                Console.Write("c:" + i + " ");
                if (i > 200000)
                    flag = false;
            }
        }
        static void Main(string[] args)
        {
            Thread a = new Thread(A);
            Thread b = new Thread(B);
            Thread c = new Thread(C);
            a.Priority = ThreadPriority.Highest;
            b.Priority = ThreadPriority.Lowest;
            a.Start();
            b.Start();
            a.Join();
            Console.WriteLine("a线程结束");
            b.Join();
            Console.WriteLine("b线程结束");
        }
    }
}

线程池

线程池中的所有线程都是后台线程 ,如果进程的所有前台线程都结束了,所有的后台线程就会停
止。
不能把入池的线程改为前台线程 。
不能给入池的线程设置优先级或名称。
入池的线程只能用于时间较短的任务。 如果线程要一直运行(如 Word的拼写检查器线程),就应使
用Thread类创建一个线程。
namespace _20_线程池
{
    internal class Program
    {
        static void Download(object s)
        {
            for (int i = 0; i <3;i++)
            {
                Console.WriteLine("线程"+Thread.CurrentThread.ManagedThreadId+"正在下载");
                Thread.Sleep(100);
            }
            
        }
        static void Main(string[] args)
        {
            for(int i = 0; i < 10;i++) 
            {
                ThreadPool.QueueUserWorkItem(Download);
            }
            Thread.Sleep(5000);
        }
    }
}

任务

任务有两种启动方式,需要注意的是 任务是后台线程

连续任务

如果一个任务t1的执行是依赖于另一个任务t2的,那么就需要在这个任务t2执行完毕后才开
始执行t1。这个时候我们可以使用连续任务。
连续任务除了第一个任务之外方法都要有参数
namespace _21_任务
{
    internal class Program
    {
        static void DownLoad()
        {
            Console.WriteLine("正在下载,请等待...");
            Thread.Sleep(1000);
        }

        static void Ok(object a)
        {
            Console.WriteLine("下载完成");
        }
        static void Main(string[] args)
        {
            //TaskFactory tf = new TaskFactory();
            //Task T = tf.StartNew(DownLoad);

            //Task t = new Task(DownLoad);
            //t.Start();

            Task t1 = new Task(DownLoad);
            Task t2 = t1.ContinueWith(Ok);
            t1.Start();

            Thread.Sleep(1500);//任务是后台线程
        }
    }
}

资源访问冲突问题

当有多个地方同时访问一个资源时,可能会导致资源冲突(例如一个变量被多个地方使用),此时可以用锁的方式防止被多次调用

缺点:运行速度会降低

namespace _22_资源访问冲突问题
{
    internal class Class1
    {
        private object _lock = new object();
        private int state = 5;
        public void changestate() 
        {
            lock (_lock)
            {
                if (state == 5)
                {
                    state++;
                    Console.WriteLine(Thread.CurrentThread.ManagedThreadId + "状态为:" + state);
                }
                state = 5;
            }
        }

    }
    internal class Program
    {
        static void Main(string[] args)
        {
            Class1 c1 = new Class1();
            for (int i = 0; i < 100; i++) 
            {
                Thread thread = new Thread(c1.changestate);
                thread.Start();
            }
        }
    }
}

死锁问题

有多个锁的时候需要注意锁的先后顺序,下面这个讲的很好

408-多线程的死锁问题_哔哩哔哩_bilibili

你可能感兴趣的:(c#,学习,开发语言)