作者 孫東風 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提供了一套類似於線程池的機制,通過它可以更加方便的進行多線程的並行作業,從而使得程式員從繁雜的多線程共用資料管理和死結問題中解脫出來。