作者 孫東風 2011-1-12 轉載請注明出處
引言
在涉及多線程並發操作時,如何管理多線程對共享數據的訪問以及防止線程間的死鎖問題是個很重要的話題。在Java語言中,從Java 5開始,Java提供了自己的線程池ThreadPoolExecutor類;在iPhone中則提供了NSOperationQueue類進行多線程的管理和調度。
什麼是線程池?
線程池到底是怎麼一回事呢?其實線程池的原理很簡單,類似於操作系統中的緩沖區的概念,它的典型的執行流程如下:
首先,啟動若干數量的線程,並讓這些線程處於睡眠狀態
其次,當客戶端有新的請求時,線程池會喚醒某一個睡眠線程,讓它來處理客戶端的請求
最後,當請求處理完畢,線程又處於睡眠狀態
Java線程池
線程池可以由程序員自己來實現,但是從Java 5開始,Java語言自帶了線程池的類ThreadPoolExecutor,這個類提供了典型的線程池管理的接口,來研究ThreadPoolExecutor類的實現無疑更有借鑒意義。
ThreadPoolExcutor類常用的構造方式為
ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler)
參數corePoolSize為線程池維護線程的最少數量
參數maximumPoolSize為線程池維護線程的最大數量
參數keepAliveTime為線程池維護線程所允許的空閒時間
參數unit為線程池維護線程所允許的空閒時間的單位
參數workQueue為線程池所使用的緩沖隊列
參數handler為線程池對拒絕任務的處理句柄
一個任務可以通過excute(Runnable)方法被添加到線程池,任務就是一個實現了Runnable接口的對象,而線程池通過Runnable類型對象的run()方法來執行任務。
典型的用法如下:
首先,構造一個線程池
ThreadPoolExecutor threadPool =
new ThreadPoolExecutor(2,4,3,TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(3),new ThreadPoolExecutor.DiscardOldestPolicy());
for(int i = 1;i <= 5;i++)
{
try
{
String task = “task@”+i;
System.out.println(“put”+task);
threadPool.execute(new ThreadPoolTask());
}
}
catch(Exception e)
{
e.printStackTrace();
}
而線程池所要執行的任務對象需要實現Runnable接口,線程池執行任務對象時調用任務對象的run()方法,它的實現代碼如下:
public class ThreadPoolTask implements Runnable{
ThreadPoolTask(){}
public void run(){
System.out.println(“start execute”);
}
}
iPhone操作隊列
iPhone本身也支持多線程開發,同樣,NSThread類提供對多線程開發的支持時也面臨多線程的共享數據管理和死鎖問題,於是iPhone也提供了類似於Java線程池的解決方案:任務隊列NSOperationQueue類。
和Java語言的Runnable接口一樣,iPhone提供了NSOperation接口進行任務對象的封裝,而通過將任務對象加入到NSOperationQueue隊列,NSOperationQueue隊列會分配線程進行任務對象的執行,任務對象的執行通過- (void)main方法,下面是典型的任務對象和任務隊列的實現:
@interface ThreadPoolTask:NSOperation
{
}
@end
@implementation ThreadPoolTask
- (void)main
{
NSLog(@”start execute”);
}
@end
和Java語言中一樣,構造一個多線程池並添加任務對象到線程池中,線程池會調用任務對象的- (void)main方法執行任務,iPhone中典型的任務隊列的實現如下:
NSOperationQueue* threadPool = [[NSOperation alloc] init];
[threadPool setMaxConcurrentOperationCount:4];
for(int i = 1;i <= 5;i++)
{
NSString* task = [NSString stringWithFormat:@”task %d”,i];
NSLog(@“put %@”,task);
threadPool.add([[ThreadPoolTask alloc] init));
}
可以看到,iPhone通過NSOperationQueue提供了一套類似於線程池的機制,通過它可以更加方便的進行多線程的並發操作,從而使得程序員從繁雜的多線程共享數據管理和死鎖問題中解脫出來。