环境:Mac OS X 10.9、Xcode 5.0.2、ARC 禁用。
问题:所有线程完成作业后如何释放属性内存。请参见下面的示例。
我正在用一个按钮“(IBAction)btnRun:(id)sender”创建迷你示例。
示例读取 txt 文件并填充 NSArray 属性 (sharedListWords)。然后运行两个线程,每个线程显示单词,
请参阅OUT 部分。当线程完成一项工作时,属性 (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.
最佳答案
根据 Martins 的指示,这是正确的代码。
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
关于ios - 属性、线程、内存管理和摇滚乐,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23412613/
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
我正在使用i18n从头开始构建一个多语言网络应用程序,虽然我自己可以处理一大堆yml文件,但我说的语言(非常)有限,最终我想寻求外部帮助帮助。我想知道这里是否有人在使用UI插件/gem(与django上的django-rosetta不同)来处理多个翻译器,其中一些翻译器不愿意或无法处理存储库中的100多个文件,处理语言数据。谢谢&问候,安德拉斯(如果您已经在rubyonrails-talk上遇到了这个问题,我们深表歉意) 最佳答案 有一个rails3branchofthetolkgem在github上。您可以通过在Gemfi
我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog
对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序