2009-08-05 20 views
4

私はJava開発を長年してiPhone開発に取り掛かりつつあります。私はJavaのBlockingQueueに相当するObjective-Cを探しています。そんなことはありますか?Objective-Cに相当するJavaのBlockingQueue?

私は物事を間違った道を進んだ場合は、ここで私が達成しようとしているものです:

私は、ネットワークサーバからプルデータのチャンクを一度に表示します。ユーザーがネットワークの遅れに気付かないように、私はいつもデータのプリフェッチをいくつかしたいと思っています。 Javaの土地では、私のフェッチスレッドと私の表示スレッドの間にスレッドセーフキューを使用したいと思います。

答えて

2

NSOperationをスピンオフして、データが戻ってきたときに通知をポストすることができます。 NSURLConnectionセッションをカプセル化する方法を示しNSOperationとの同時実行上のデイブDribinのブログ記事を見てみましょう:

http://www.dribin.org/dave/blog/archives/2009/05/05/concurrent_operations/

あなたはNSURLConnectionが適切であるWebサービスやサイトへのアクセスについて話されていない場合は、代わりにすることができますそれはまっすぐにTCP/IPまたはUDPかどうココア非同期ソケットを使用します。

http://code.google.com/p/cocoaasyncsocket/

よろしく、

+0

Dave Dribinのブログへのリンクを投稿してくれてありがとう。それは私の人生を救った。バックグラウンドスレッドに留まるために非同期メソッドのアイドルループを実行していました。 – Ben

1

このようなことはネイティブにはありません。おそらくネットワークオブジェクトのキューを管理する独自のクラスを作成する必要があります。 (そして、あなたはobjects配列から最上位オブジェクトをポップして返すようにgetNextChunkを実装し、[objects count]が一定値未満であれば、いくつかのより多くのオブジェクトをフェッチするスレッドを起動することができ

@interface ObjcBlockingQueue : NSObject { 
    // The objects that you're holding onto 
    NSArray *objects; 
} 

@property(nonatomic,retain) NSArray *objects; 

- (ServerData *)getNextChunk;

:あなたのヘッダーは次のようになりますおそらくObjcBlockingQueueがデリゲートであるNSURLConnectionを使用しています)。キューを事前に埋め込むために、オーバーライドされたinitメソッドの中で起動されたそのスレッド/接続を持つこともできます。

また、あなたの表示スレッドは、それがすぐに何か新しいものを表示することができますか、それはロードメッセージを表示する必要がある場合かどうかをお知らせします

- (BOOL)isChunkAvailable;

メソッドを追加することについて考えたいかもしれません。データを表示する場所やアプリケーションの構造によっては、ObjcBlockingQueueをシングルトンクラスにする価値があります。

+0

ファンタスティック。このような迅速な答えに感謝します。私が得意でないのは、スレッドの安全性がどのように機能するかです。 Javaでは、ArrayListのような基本的なデータコンテナはスレッドセーフではなく、NsMutableArrayドキュメントは別のことを言っていないので、スレッドセーフではないと考えています。それを考えると、NSMutableArrayで@syncronizedを行うだけですか? –

+1

これは良い答えですが、Javaとはいくつかの点で異なるCのスレッディングをかなりよく理解する必要があります。 Javaから何かを再実装する独自のクラスを書く前に、NSOperationサブクラスとNSOperationキューの使用を検討することをお勧めします。NSOperationが完了した時点で通知を受け取ることができます。その時点で、(その操作に完全にロードされたデータを含むデータプロパティのような)いくつかのプロパティには安全にアクセスできます。 –

+0

@ウィリアム:それは確かに一つの可能​​性です。もしあなたが気に入っていれば、オブジェクトに対する自分のロックを管理することもできます。 NSOperationのサブクラスとキューを使うもう1つの方法は、@ Jasonが述べたようにです。 「The Objective-C Programming Language:Threading」(http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocThreading.html)と「スレッディングプログラミングガイド」(http:// developer .apple.com/documentation/Cocoa/Conceptual/Multithreading/Introduction/Introduction.html#// apple_ref/doc/uid/10000057i-CH1-SW1) – Tim

8

はここimplemenですキューとデキューメソッドを使用したブロッキングキューの作成。 1つのスレッドがdequeueUnitOfWorkWaitingUntilDate:を呼び出すループに入り、2つ目のスレッドがqueueUnitOfWork:を呼び出している間に作業単位を処理することが期待されます。

@interface MyBlockingQueue : NSObject { 
    NSMutableArray *queue; 
    NSConditionLock *queueLock; 
} 
- (id)dequeueUnitOfWorkWaitingUntilDate:(NSDate *)timeoutData; 
- (void)queueUnitOfWork:(id)unitOfWork; 
@end 

enum { 
    kNoWorkQueued = 0, 
    kWorkQueued = 1 
} 

@implementation MyBlockingQueue 
- (id)init { 
    if ((self = [super init])) { 
     queueLock = [[NSConditionLock alloc] initWithCondition:kNoWorkQueued]; 
     workItems = [[NSMutableArray alloc] init]; 
    } 
    return self; 
} 

- (void)dealloc { 
    [queueLock release]; 
    [workItems release]; 
    [super dealloc]; 
} 

- (id)dequeueUnitOfWorkWaitingUntilDate:(NSDate *)timeoutDate { 
    id unitOfWork = nil; 
    if ([queueLock lockWhenCondition:kWorkQueued beforeDate:timeoutDate]) { 
     unitOfWork = [[[queue objectAtIndex:0] retain] autorelease]; 
     [queue removeObjectAtIndex:0]; 
     [queueLock unlockWithCondition:([workItems count] ? kWorkQueued : kNoWorkQueued)]; 
    } 
    return unitOfWork; 
} 

- (void)queueUnitOfWork:(id)unitOfWork { 
    [queueLock lock]; 
    [queue addObject:unitOfWork]; 
    [queueLock unlockWithCondition:kWorkQueued]; 
} 
@end 
+0

lockWhenCondition:beforeDate:の戻り値を確認する必要があります。そうでなければ、ロックを取得せずに時間が経過した場合、キューにIndexOutOfBounds例外が発生します。また、queueUnitOfWork:theConditionLockはqueueLockでなければなりません。 –

+0

実際には、最初にロックを取得したことがないので、ロックを解除すると例外がスローされます。 –

+0

もちろん、私の見落としです。それを指摘してくれてありがとう。一定。 –