
四、线程池
线程池:需要的时候从池中获取线程不用自行创建,使用完毕不需要销毁线程而是放回池中,从而减少创建和销毁线程对象的开销。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。这就说明第一次请求线程池的时候,线程池建立了一个线程,当它执行完成之后就以挂起状态回到了线程池,在最后一次请求的时候,再次唤醒了该线程执行任务。这样就很容易理解了。
在这里我还发现了一个问题,就是,每次运行的时候,输出的内容的顺序都不一定是一样的。(不只是线程池,前面的也是)因为,我没有给任何线程设置优先级(线程池不能设置线程的优先级),这里其实就涉及到线程安全的问题了,很明显现在这样是非线程安全的。让我举个栗子形容一下的话,就像以前在学校下课了去吃饭一样,一拥而上,毫无秩序。
线程安全就先不说,留在后面再说(包括前面所提到的线程同步的问题),这篇博客旨在理解多线程。因为我也没有太深的理解。。。
上面我们已经实现了无参数和有参数以及自定义参数多线程的实例,可是还有一个共同的问题那就是都没有返回值。当我们用多线程做实际开发的时候大部分都是会需要返回值的,那么我们可以使用成员变量来试试。

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
这么讽刺不要脸的称号美国居然还欣然自得
不动武就惊跑了美帝
阿拉觉察也是合理的