首页 > 代码库 > 多线程编程几个误区
多线程编程几个误区
多线程的优势是针对单线程而言的
对多线程的布道在几年前较为常见,那时候PC已经完成从单核到多核的转变,但很多应用程序依然是单线程的,无法发挥多核CPU的威力。多线程的优势也就是让几个内核同时工作,最大化CPU的计算能力。
如果发现很多工作特别是IO工作运行在GetMessage或者Select线程上,就应该考虑多线程了。
线程池的优势是针对新建线程而言的
为什么要使用线程池,因为线程的创建和销毁是很昂贵的操作。对于昂贵的对象我们要尽量复用,其结果就是各种池,比如线程池,连接池。使用线程池可以省下线程创建与销毁的开销,设计良好的线程池还可以防止在负载较高时大量线程耗光内存。
如果代码中有 new Thread() 考虑使用线程池代替。
使用线程池线程进行同步IO操作仍然是同步的
这可能是最容易被误解的地方。特别是在Java中,当有人问:“这里的同步访问怎样防止进程阻塞”时,最常见的回答就是“使用线程池”。这个回答有其合理性,比如当前线程是UI线程或者读取socket的线程时,这些线程是不应该阻塞在IO上的。但这个问题的另一面是:IO操作依然是阻塞的,只不过这回阻塞在worker线程上了。这一点很重要,因为有时候我们本来就跑在worker上,这个时候再往线程池里面扔就没有意义,甚至可能造成两个线程都被阻塞。
在Java的世界中,很多项目,甚至很多大项目,比如CXF和Jersey,都是使用线程池来模拟异步操作。这种方法在负载比较低的时候能够加快响应,但一旦线程池出现排队则没什么用甚至有负作用。这是Java一个很尴尬的地方,.net在提出异步方法时把BCL也更新了以适应变化。尽管Java从1.4开始就有了non-blocking IO,但NIO即使在今天仍然算得上新事物,采用率很低。尤其是jdbc没有异步接口成功了一个很大的问题。实践中如果追求异步便要求所有代码都异步,如果sql访问不能异步则一切都是空谈。
其实异步的情况下并不需要多线程
异步的好处关键在于控制了线程数量,这带来两个直接的好处:
- 节省内存,大并发的情况下线程会吃掉大量内存
- 避免了线程上下文切换的额外开销
理论上讲每个CPU使用一个线程,便能够最大限度的发挥硬件的潜力同时不产生浪费,当然这是很理想的情况。现实是应用程序在OS的调度下和其它程序共享资源。但避免线程切换带来的好处在大并发的情况下依然是很明显的。
多线程编程几个误区