b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

C# 多线程编程第一步

电脑杂谈  发布时间:2019-06-18 09:11:23  来源:网络整理

线程与线程池_windows编程线程_多线程编程

四、线程池

线程池:需要的时候从池中获取线程不用自行创建,使用完毕不需要销毁线程而是放回池中,从而减少创建和销毁线程对象的开销。l 重用线程池中的线程,避免因为线程创建和销毁所带来的性能开销。而线程池则是:一开始就创建两个线程,然后将这三个任务加入到线程池的任务队列中,让线程池利用这两个线程去完成这三个任务。

   class Program
    {
        static void Main(string[] args)
        {
            ThreadDemoClass demoClass = new ThreadDemoClass();
            //设置当没有请求时线程池维护的空闲线程数
            //第一个参数为辅助线程数
            //第二个参数为异步 I/O 线程数
            ThreadPool.SetMinThreads(5, 5);
            //设置同时处于活动状态的线程池的线程数,所有大于次数目的请求将保持排队状态,直到线程池变为可用
            //第一个参数为辅助线程数
            //第二个参数为异步 I/O 线程数
            ThreadPool.SetMaxThreads(100, 100);
            //使用委托绑定线程池要执行的方法(无参数)
            WaitCallback waitCallback1 = new WaitCallback(demoClass.Run1);
            //将方法排入队列,程池变为可用时执行
            ThreadPool.QueueUserWorkItem(waitCallback1);
            //使用委托绑定线程池要执行的方法(有参数)
            WaitCallback waitCallback2 = new WaitCallback(demoClass.Run1);
            //将方法排入队列,程池变为可用时执行
            ThreadPool.QueueUserWorkItem(waitCallback2,"Brambling");
            UserInfo userInfo = new UserInfo();
            userInfo.Name = "Brambling";
            userInfo.Age = 33;
            //使用委托绑定线程池要执行的方法(有参数,自定义类型的参数)
            WaitCallback waitCallback3 = new WaitCallback(demoClass.Run2);
            //将方法排入队列,程池变为可用时执行
            ThreadPool.QueueUserWorkItem(waitCallback3, userInfo);
            Console.WriteLine();
            Console.WriteLine("Main thread working...");
            Console.WriteLine("Main thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());
            Console.ReadKey();
        }
    }
    public class ThreadDemoClass
    {
        public void Run1(object obj)
        {
            string name = obj as string;
            Console.WriteLine();
            Console.WriteLine("Child thread working...");
            Console.WriteLine("My name is " + name);
            Console.WriteLine("Child thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());
        }
        public void Run2(object obj)
        {
            UserInfo userInfo=(UserInfo)obj;
            Console.WriteLine();
            Console.WriteLine("Child thread working...");
            Console.WriteLine("My name is " + userInfo.Name);
            Console.WriteLine("I'm " + userInfo.Age + " years old this year");
            Console.WriteLine("Child thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());
        }
    }
    public class UserInfo
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }

执行结果:

使用线程池建立的线程也可以选择传递参数或不传递参数,并且参数也可以是值类型或引用类型(包括自定义类型)。看上面的结果发现了什么?没错,第一次执行的方法的线程ID为6,最后一次执行的方法的线程ID也为6。这就说明第一次请求线程池的时候,线程池建立了一个线程,当它执行完成之后就以挂起状态回到了线程池,在最后一次请求的时候,再次唤醒了该线程执行任务。这样就很容易理解了。

在这里我还发现了一个问题,就是,每次运行的时候,输出的内容的顺序都不一定是一样的。(不只是线程池,前面的也是)因为,我没有给任何线程设置优先级(线程池不能设置线程的优先级),这里其实就涉及到线程安全的问题了,很明显现在这样是非线程安全的。让我举个栗子形容一下的话,就像以前在学校下课了去吃饭一样,一拥而上,毫无秩序。

线程安全就先不说,留在后面再说(包括前面所提到的线程同步的问题),这篇博客旨在理解多线程。因为我也没有太深的理解。。。

上面我们已经实现了无参数和有参数以及自定义参数多线程的实例,可是还有一个共同的问题那就是都没有返回值。当我们用多线程做实际开发的时候大部分都是会需要返回值的,那么我们可以使用成员变量来试试。

windows编程线程_线程与线程池_多线程编程

   class Program
    {
        List<UserInfo> userInfoList = new List<UserInfo>();
        static void Main(string[] args)
        {
            Program program = new Program();
            ParameterizedThreadStart threadStart = new ParameterizedThreadStart(program.Run);
            Thread thread = null;
            UserInfo userInfo = null;
            for (int i = 0; i < 3; i++)
            {
                userInfo = new UserInfo();
                userInfo.Name = "Brambling" + i.ToString();
                userInfo.Age = 33 + i;
                thread = new Thread(threadStart);
                thread.Start(userInfo);
                thread.Join();
            }
            foreach (UserInfo user in program.userInfoList)
            {
                Console.WriteLine("My name is " + user.Name);
                Console.WriteLine("I'm " + user.Age + " years old this year");
                Console.WriteLine("Thread ID is:" + user.ThreadId);
            }
            
            Console.ReadKey();
        }
        public void Run(object obj)
        {
            UserInfo userInfo = (UserInfo)obj;
            userInfo.ThreadId = Thread.CurrentThread.ManagedThreadId;
            userInfoList.Add(userInfo);
        }
    }

执行结果:

这是不行的,我们可以用反证法来说明这个问题,因为我们有时候调用一个方法时也可以不定义返回结果变量,即不要关心其返回结果,例如,我们调用map.remove(key)方法时,虽然remove方法有返回值多线程编程,但是我们通常都不会定义接收返回结果的变量,这时候假设该类中有两个名称和参数列表完全相同的方法,仅仅是返回类型不同,java就无法确定编程者倒底是想调用哪个方法了,因为它无法通过返回结果类型来判断。代码示例:线程id=beginthread(监视)//方法1:启动线程,并且将启动的线程的id返回给变量线程idbeginthread监视//方法2:启动线程,没有返回值的写法编程好习惯,启动了线程之后,不需要使用的时候要记得停止线程。c、当其他线程调用pthread_cond_signal或pthread_cond_broadcast时,会唤醒相应条件变量等待的线程,此时被唤醒的线程,可以参与调度了,此时被唤醒的线程继续执行pthread_cond_wait()函数,函数pthread_cond_wait()返回之前,会重新给条件变量对应的互斥量上锁,在这里就是nready.mutex,若该函数成功返回,则当前线程有重新获得了nready.mutex锁,当然nready.mutex也可能被其他线程继续占有,此时线程再次阻塞。

所以也就有了下面的方法,使用委托异步调用的方法。

五、异步委托

委托的异步调用有两个比较重要的方法:BeginInvoke() 和 EndInvoke()

   class Program
    {
        //定义一个委托类
        private delegate UserInfo MyDelegate(UserInfo userInfo);
        static void Main(string[] args)
        {
            ThreadDemoClass demoClass = new ThreadDemoClass();
            List<UserInfo> userInfoList = new List<UserInfo>();
            UserInfo userInfo = null;
            UserInfo userInfoRes = null;
            //创建一个委托并绑定方法
            MyDelegate myDelegate = new MyDelegate(demoClass.Run);
            for (int i = 0; i < 3; i++)
            {
                userInfo = new UserInfo();
                userInfo.Name = "Brambling" + i.ToString();
                userInfo.Age = 33 + i;
                //传入参数并执行异步委托
                IAsyncResult result = myDelegate.BeginInvoke(userInfo,null,null);
                //异步操作是否完成
                while (!result.IsCompleted)
                {
                    Thread.Sleep(100);
                    Console.WriteLine("Main thread working...");
                    Console.WriteLine("Main thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());
                    Console.WriteLine();
                }
                //结束异步委托,并获取返回值
                userInfoRes = myDelegate.EndInvoke(result);
                userInfoList.Add(userInfoRes);
            }
            foreach (UserInfo user in userInfoList)
            {
                Console.WriteLine("My name is " + user.Name);
                Console.WriteLine("I'm " + user.Age + " years old this year");
                Console.WriteLine("Thread ID is:" + user.ThreadId);
            }
            
            Console.ReadKey();
        }
    }
    public class ThreadDemoClass
    {
        public UserInfo Run(UserInfo userInfo)
        {
            userInfo.ThreadId = Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine("Child thread working...");
            Console.WriteLine("Child thread ID is:" + userInfo.ThreadId);
            Console.WriteLine();
            return userInfo;
        }
    }


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-106819-1.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    • 田午
      田午

      阿拉觉察也是合理的

    • 王海珍
      王海珍

      这么讽刺不要脸的称号美国居然还欣然自得

    • 赵亚楠
      赵亚楠

      不动武就惊跑了美帝

    热点图片
    拼命载入中...