环境:Mac OS X 10.9,Xcode 5.0.2,ARC禁用。
问题:所有线程完成工作后如何释放属性的空闲内存。见下面的例子。
我用一个按钮创建迷你示例“(IBAction)btnRun:(id)sender”。
示例读取txt文件并填写NSArray属性(sharedListWords)。然后运行两个线程,每个线程显示单词,
参见 OUT Section 。当线程完成一个作业时,属性(self.sharedListWords)没有被释放!但是我想要为(self.sharedListWords)属性分配的空闲内存。动作“btnRun”在线程完成作业之前退出,我不能在此动作中释放(self.sharedListWords)。
线程完成作业后属性(self.sharedListWords)的可用内存是多少?是好的答案here通过创建依赖操作jobFinished(),但是如何正确释放属性?
这是我在Objective-c上的第一个多线程程序,我很乐意进行调整。
AppDelegate.h:
#import <Cocoa/Cocoa.h>
@interface AppDelegate : NSObject <NSApplicationDelegate>
{
volatile int32_t sharedIndex; // Shared between threads, current index in array
NSOperationQueue* operationQueue;
}
@property (assign) IBOutlet NSWindow *window;
// Shared between threads, list of words
@property (atomic, retain) NSArray* sharedListWords;
- (void)worker;
@end
AppDelegate.m:
#import "AppDelegate.h"
@implementation AppDelegate
- (IBAction)btnRun:(id)sender
{
// Read txt file dictionary of words, where is each words in new line.
NSString* dictionaryFilePath = [NSString stringWithFormat:@"/Users/admin/dictionary.txt"];
NSString* fileContents = [NSString stringWithContentsOfFile:dictionaryFilePath
encoding:NSUTF8StringEncoding error:nil];
// Get array of string separated by new line
self.sharedListWords = [fileContents componentsSeparatedByCharactersInSet:
[NSCharacterSet newlineCharacterSet]];
//self.sharedListWords = @[@"one",@"two",@"three",@"four",@"five",@"six",@"seven",@"eight",@"nine",@"ten"];
self->sharedIndex = -1;
int numberOfThreads = 2;
// Run method working() in separate threads
for(int i=0; i<numberOfThreads; ++i)
{
//////////////////////////////////////////
// Create a thread
// Create new NSOperatin object with function puting in @selector() for run in other thread.
NSOperation* startBruteOper = [[NSInvocationOperation alloc]
initWithTarget:self selector:@selector(worker) object:nil];
// Add the operation to the queue and let it to be executed.
[operationQueue addOperation:startBruteOper];
[startBruteOper release];
/////////////////////////////////////////
}
}
- (void)worker
{
unsigned long countWords = [self.sharedListWords count];
int32_t index = 0;
// Use atomic operation for thread safe
while( (index = OSAtomicIncrement32( &(self->sharedIndex) ) ) < countWords )
{
NSLog(@"[%@] working on \"%@\"",
[NSThread currentThread],
[self.sharedListWords objectAtIndex:index]);
}
NSLog(@"[%@] work is finish.", [NSThread currentThread]);
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Multithreading queue list
operationQueue = [[NSOperationQueue alloc] init];
}
@end
OUT部分:
[<NSThread: num = 2}] working on "one"
[<NSThread: num = 3}] working on "two"
[<NSThread: num = 2}] working on "three"
[<NSThread: num = 3}] working on "four"
[<NSThread: num = 2}] working on "five"
[<NSThread: num = 3}] working on "six"
[<NSThread: num = 2}] working on "seven"
[<NSThread: num = 3}] working on "eight"
[<NSThread: num = 2}] working on "nine"
[<NSThread: num = 3}] working on "ten"
[<NSThread: num = 2}] work is finish.
[<NSThread: num = 3}] work is finish.
答案 0 :(得分:2)
这是马丁斯指示后的正确代码。
AppDelegate.h:
#import <Cocoa/Cocoa.h>
@interface AppDelegate : NSObject <NSApplicationDelegate>
{
volatile int32_t sharedIndex; // Shared between threads, current index in array
NSOperationQueue* operationQueue;
}
@property (assign) IBOutlet NSWindow *window;
// Shared between threads, list of words
@property (atomic, retain) NSArray* sharedListWords;
- (void)worker;
@end
AppDelegate.m:
#import "AppDelegate.h"
@implementation AppDelegate
- (IBAction)btnRun:(id)sender
{
// Read txt file dictionary of words, where is each words in new line.
NSString* dictionaryFilePath = [NSString stringWithFormat:@"/Users/admin/dictionary.txt"];
NSString* fileContents = [NSString stringWithContentsOfFile:dictionaryFilePath
encoding:NSUTF8StringEncoding error:nil];
// Get array of string separated by new line
self.sharedListWords = [fileContents componentsSeparatedByCharactersInSet:
[NSCharacterSet newlineCharacterSet]];
//self.sharedListWords = @[@"one",@"two",@"three",@"four",@"five",@"six",@"seven",@"eight",@"nine",@"ten"];
self->sharedIndex = -1;
int numberOfThreads = 2;
NSOperation* jobFinishedOper = [[NSInvocationOperation alloc]
initWithTarget:self selector:@selector(jobFinished) object:nil];
// Run method working() in separate threads
for(int i=0; i<numberOfThreads; ++i)
{
//////////////////////////////////////////
// Create a thread
// Create new NSOperatin object with function puting in @selector() for run in other thread.
NSOperation* startBruteOper = [[NSInvocationOperation alloc]
initWithTarget:self selector:@selector(worker) object:nil];
// Add the operation to the queue and let it to be executed.
[operationQueue addOperation:startBruteOper];
[jobFinishedOper addDependency:startBruteOper]; // 'jobFinishedOper' run only when 'startBruteOper' finished!
[startBruteOper release];
/////////////////////////////////////////
}
// 'jobFinishedOper' run only when all prevous operation is finished!
[operationQueue addOperation:jobFinishedOper];
[jobFinishedOper release];
}
- (void)worker
{
unsigned long countWords = [self.sharedListWords count];
int32_t index = 0;
// Use atomic operation for thread safe
while( (index = OSAtomicIncrement32( &(self->sharedIndex) ) ) < countWords )
{
NSLog(@"[%@] working on \"%@\"",
[NSThread currentThread],
[self.sharedListWords objectAtIndex:index]);
}
NSLog(@"[%@] work is finish.", [NSThread currentThread]);
}
- (void)jobFinished
{
self.sharedListWords = nil;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Multithreading queue list
operationQueue = [[NSOperationQueue alloc] init];
}
@end
答案 1 :(得分:1)
您可以在所有&#34; worker&#34;上添加依赖的其他操作。操作,如 在
中描述该操作在所有依赖项完成后运行,因此您可以调用
self.sharedListWords = nil;
在完成的操作中释放数组。