1.說下線程和進(jìn)程的區(qū)別
答:(1)一個(gè)線程只能屬于一個(gè)進(jìn)程,而一個(gè)進(jìn)程可以有多個(gè)線程,但至少有一個(gè)線程。線程是操作系統(tǒng)可識(shí)別的最小執(zhí)行和調(diào)度單位。
(2)資源分配給進(jìn)程,同一進(jìn)程的所有線程共享該進(jìn)程的所有資源。 同一進(jìn)程中的多個(gè)線程共享代碼段(代碼和常量),數(shù)據(jù)段(全局變量和靜態(tài)變量),擴(kuò)展段(堆存儲(chǔ))。但是每個(gè)線程擁有自己的棧段,棧段又叫運(yùn)行時(shí)段,用來存放所有局部變量和臨時(shí)變量。
(3)處理機(jī)分給線程,即真正在處理機(jī)上運(yùn)行的是線程。
(4)線程在執(zhí)行過程中,需要協(xié)作同步。不同進(jìn)程的線程間要利用消息通信的辦法實(shí)現(xiàn)同步。
2.如何保證線程安全
一塊資源可能會(huì)被多個(gè)線程共享,也就是多個(gè)線程可能會(huì)訪問同一塊資源,比如多個(gè)線程訪問同一個(gè)對(duì)象、同一個(gè)變量、同一個(gè)文件。當(dāng)多個(gè)線程訪問同一塊資源時(shí),很容易引發(fā)數(shù)據(jù)錯(cuò)亂和數(shù)據(jù)安全問題。此時(shí),我們需要用線程鎖來解決。
(1)nonatomic atomic:
使用atomic多線程原子性控制,atomic的原理給setter加上鎖, getter不會(huì)加鎖。OC在定義屬性時(shí)有nonatomic和atomic兩種選擇
atomic:原子屬性,為setter方法加鎖(默認(rèn)就是atomic)
nonatomic:非原子屬性,不會(huì)為setter方法加鎖
(2)使用GCD實(shí)現(xiàn)atomic操作:給某字段的setter和getter方法加上同步隊(duì)列:
- (void)setCount:(NSInteger)newcount{
dispatch_sync(_synQueue, ^{ count = newcount; });
}
- (NSInteger)count
{
__block NSInteger localCount;
dispatch_sync(_synQueue, ^{
localCount = count;
});
return localCount;
}
(3)使用NSLock
- (void)threadRunLock
{
_lock = [[NSLock alloc]init];
while (true)
{
[_lock lock];
if (self.number > 0 )
{
[NSThread sleepForTimeInterval:0.5];
self.number --;
NSLog(@"thread:%@ ---> %ld",[[NSThread currentThread] name],self.number);
}
[_lock unlock];
}
}
相當(dāng)于給代碼片段加上lock了,所以依次輸出9-0
(4)使用互斥鎖
使用格式
@synchronized(鎖對(duì)象) { // 需要鎖定的代碼 }
注意:鎖定1份代碼只用1把鎖,用多把鎖是無效的
-(void)sellTickets
{
while (true)
{
@synchronized(self)
{
//只能加一把鎖
//1.先檢查票數(shù)
int count=self.leftTicketsCount;
if (count>0)
{
//暫停一段時(shí)間
[NSThread sleepForTimeInterval:0.002];
//2.票數(shù)-1
self.leftTicketsCount= count-1;
//獲取當(dāng)前線程
NSThread *current=[NSThread currentThread];
NSLog(@"%@--賣了一張票,還剩余%d張票",current,self.leftTicketsCount);
}
else
{
//退出線程
[NSThread exit];
}
}
}
}
互斥鎖的優(yōu)缺點(diǎn):
優(yōu)點(diǎn):能有效防止因多線程搶奪資源造成的數(shù)據(jù)安全問題
缺點(diǎn):需要消耗大量的CPU資源
3、了解哪些設(shè)計(jì)模式
(1)代理模式
(2)觀察者模式
(3)MVC模式
(4)單例模式
4、堆和棧的區(qū)別,工程項(xiàng)目中的哪些數(shù)據(jù)是儲(chǔ)存在堆中、哪些在棧中
在引入堆和棧之前,先要知道,iOS中的內(nèi)存管理范圍:
oc對(duì)象需要進(jìn)行內(nèi)存管理,非oc對(duì)象不需要進(jìn)行內(nèi)存管理,比如基本數(shù)據(jù)類型
所以:
OC對(duì)象存放于堆里面(堆內(nèi)存要程序員手動(dòng)回收)
非OC對(duì)象一般放在棧里面(棧內(nèi)存會(huì)被系統(tǒng)自動(dòng)回收)
堆里面的內(nèi)存是動(dòng)態(tài)分配的,所以也就需要程序員手動(dòng)的去添加內(nèi)存、回收內(nèi)存
堆和棧的區(qū)別:
棧是吃了吐 LIFO(先進(jìn)后出)
堆是吃了拉 FIFO(先進(jìn)先出)
5、iOS中的NSCopying協(xié)議,copy,MutableCopy的區(qū)別
首先我們先說兩個(gè)兩個(gè)概念:
淺復(fù)制:不拷貝對(duì)象本身,僅僅是拷貝指向?qū)ο蟮闹羔?br> 深復(fù)制:是直接拷貝整個(gè)對(duì)象內(nèi)存到另一塊內(nèi)存中
然后我們?cè)賮砜碿opy關(guān)鍵字的特點(diǎn):
修改源對(duì)象的屬性和行為,不會(huì)影響副本對(duì)象
修改副本對(duì)象的屬性和行為,不會(huì)影響源對(duì)象
一個(gè)對(duì)象可以通過copy和mutableCopy方法來創(chuàng)建一個(gè)副本對(duì)象
copy:創(chuàng)建的是不可變副本(NSString,NSArray,NSDictionary)
mutableCopy:創(chuàng)建的是可變副本(NSMutableString,NSMutableArray,NSMutableDictionary)
6、解釋屬性修飾關(guān)鍵詞的作用(weak,strong,copy,readOnly,assgin,nonatomic等)
1.assgin
此標(biāo)記說明設(shè)置器直接進(jìn)行賦值,這也是默認(rèn)值且setter方法直接將傳入?yún)?shù)賦值給實(shí)例變量,不涉及引用計(jì)數(shù)的變化,也沒有引用技術(shù)可以供管理;
主要用于非指針變量(也可以修飾指針變量,但是平時(shí)都不這么用),即用于基礎(chǔ)數(shù)據(jù)類型(例如NSInteger)和C的數(shù)據(jù)類型(int, float, double, char)另外還有id類型的屬性,總而言之,前面不需要加"*"的就可以用assign修飾;
2.retian :
表示持有特性,一般用于指針對(duì)象,例如數(shù)組(NSMutableArray,NSArray),字典對(duì)象,視圖對(duì)象(UIView ),控制器對(duì)象(UIViewController)等,這些屬性需要保存引用計(jì)數(shù);
就是說你定義了一個(gè)變量,然后這個(gè)變量在程序的運(yùn)行過程中會(huì)被更改,并且影響到其他方法,當(dāng)用retain時(shí),會(huì)釋放舊的對(duì)象,將輸入對(duì)象的索引計(jì)數(shù)+1,然后將輸入對(duì)象的值賦予新對(duì)象。
3.copy :
其setter方法是進(jìn)行Copy操作,與retain處理流程基本一樣,先舊對(duì)象release,再Copy出新的對(duì)象,retainCount為1,這是為了減少對(duì)上下文的依賴而引入的機(jī)制,區(qū)別在于copy主要用于NSString;retain是指針拷貝,copy是內(nèi)容拷貝然后新的對(duì)象開辟新內(nèi)存,引用計(jì)數(shù)為1,原來對(duì)象計(jì)數(shù)不變
4.weak:
weak是弱引用,是由ARC引入的對(duì)象變量的屬性,相當(dāng)于assign,只有在你打開ARC時(shí)才會(huì)被要求使用(但是weak只能修飾對(duì)象即指針類型的屬性和id類型的屬性,所以在ARC中修飾基本數(shù)據(jù)類型的屬性還是要用assign);
weak比assign多了一個(gè)功能,就是對(duì)象消失后把指針置為nil,避免了野指針,不是null指針,是指向“垃圾”內(nèi)存(不可用的內(nèi)存)的指針;
5.strong:
strong是強(qiáng)引用,是ARC新引入的對(duì)象變量屬性,簡(jiǎn)單講strong等同retain,只有在你打開ARC時(shí)才會(huì)被要求使用;
但是對(duì)于strong來說,它會(huì)自己判斷是選擇retain還是copy,比較方便。
6.readonly:
此標(biāo)記說明屬性是只讀的,默認(rèn)的標(biāo)記是讀寫,如果你指定了只讀,在@implementation中只需要一個(gè)讀取器,如果你使用@synthesize關(guān)鍵字,也只有讀取器方法被解析,即只會(huì)生成getter方法,不會(huì)生成setter方法;
不希望屬性在類外改變時(shí)候使用。
7.readwrite:
此標(biāo)記說明屬性會(huì)被當(dāng)成讀寫的,這也是默認(rèn)屬性。設(shè)置器和讀取器都需要在@implementation中實(shí)現(xiàn)。如果使用@synthesize關(guān)鍵字,讀取器和設(shè)置器都會(huì)被解析,即會(huì)同時(shí)生成getter和setter方法;
8.nonatomic:
非原子性訪問,對(duì)屬性賦值的時(shí)候不加鎖,不加同步,多線程并發(fā)訪問會(huì)提高性能。如果不加此屬性,則默認(rèn)是兩個(gè)訪問方法都為原子型事務(wù)訪問;
非原子操作,會(huì)簡(jiǎn)單的操作屬性的值,這會(huì)加快屬性存取的速度,但沒辦法保證在多線程環(huán)境下不出錯(cuò)。
9.atomc:
原子操作,這是默認(rèn)的,在多線程環(huán)境下,本方法設(shè)定為原子操作提供了可靠的屬性存取方法,而不用擔(dān)心并發(fā)時(shí)會(huì)產(chǎn)生問題;
這也就是說,在多線程環(huán)境下,解析的訪問器提供一個(gè)對(duì)屬性的安全訪問,從獲取器得到的返回值或者通過設(shè)置器設(shè)置的值可以一次完成,即便是別的線程也正在對(duì)其進(jìn)行訪問。
7. Object-c的類可以多重繼承么?可以實(shí)現(xiàn)多個(gè)接口么?Category是什么?重寫一個(gè)類的方式用繼承好還是分類好?為什么?
答:Object-c的類不可以多重繼承;可以實(shí)現(xiàn)多個(gè)接口,通過實(shí)現(xiàn)多個(gè)接口可以完成C++的多重繼承;Category是類別,一般情況用分類好,用Category去重寫類的方法,僅對(duì)本Category有效,不會(huì)影響到其他類與原有類的關(guān)系。
8.#import 跟#include 又什么區(qū)別,@class呢, #import<> 跟 #import”"又什么區(qū)別?
答:#import是Objective-C導(dǎo)入頭文件的關(guān)鍵字,#include是C/C++導(dǎo)入頭文件的關(guān)鍵字,使用#import頭文件會(huì)自動(dòng)只導(dǎo)入一次,不會(huì)重復(fù)導(dǎo)入,相當(dāng)于#include和#pragma once;@class告訴編譯器某個(gè)類的聲明,當(dāng)執(zhí)行時(shí),才去查看類的實(shí)現(xiàn)文件,可以解決頭文件的相互包含;#import<>用來包含系統(tǒng)的頭文件,#import””用來包含用戶頭文件。
9.這段代碼有什么問題嗎:
答:@implementation Person
- (void)setAge:(int)newAge {
self.age = newAge;
}
@end
正確寫法
{
if(_age){
[_age release];
}
_age = [newAge retain];
}
死循環(huán)(擴(kuò)展:知道如何正確寫setter和getter方法)
10. 屬性readwrite,readonly,assign,retain,copy,nonatomic 各是什么作用,在那種情況下用?
readwrite 是可讀可寫特性;需要生成getter方法和setter方法時(shí)
readonly 是只讀特性 只會(huì)生成getter方法 不會(huì)生成setter方法 ;不希望屬性在類外改變assign是賦值特性,setter方法將傳入?yún)?shù)賦值給實(shí)例變量;僅設(shè)置變量時(shí);retain表示持有特性,setter方法將傳入?yún)?shù)先保留,再賦值,傳入?yún)?shù)的retaincount會(huì)+1;copy表示拷貝特性,setter方法將傳入對(duì)象復(fù)制一份;需要完全一份新的變量時(shí)。nonatomic 非原子操作,決定編譯器生成的setter getter是否是原子操作,atomic表示多線程安全,一般使用nonatomic
11.截取字符串”20 | http://www.baidu.com”中,”|”字符前面和后面的數(shù)據(jù),分別輸出它們。
componentsSeparatedByString
NSString * str = @“20|http://www.baidu.com”;
for(NSString*s in [str componentsSeparatedByString]){
NSLog(@“%@“,s);
}
12.指出下面代碼的問題- (void)willEndStepOne:(NSObject *)userInfo{ [NSThread detachNewThreadSelector:@selector(doSomeThing:) toTarget:self withObject:userInfo];}- (void)doSomeThing:(NSObject *)userInfo{ int max_loop_times = 999999; for (int i=0; i<max_loop_times; i++) { int randNum = rand(); NSString *tmpString = [NSString stringWithFormat:@"%d", randNum]; NSLog(@"%@", tmpString); }}
13.分析json、xml的區(qū)別?json、xml解析方式的底層是如何處理的?
http://www.open-open.com/bbs/view/1324367918671
http://hi.baidu.com/fevelen/item/a25253ab76f766756cd455b6
14.Objective-C如何對(duì)內(nèi)存管理的,說說你的看法和解決方法?
Objective-C的內(nèi)存管理主要有三種方式ARC(自動(dòng)內(nèi)存計(jì)數(shù))、手動(dòng)內(nèi)存計(jì)數(shù)、內(nèi)存池。
15.內(nèi)存管理的幾條原則時(shí)什么?按照默認(rèn)法則.那些關(guān)鍵字生成的對(duì)象
需要手動(dòng)釋放?在和property結(jié)合的時(shí)候怎樣有效的避免內(nèi)存泄露?
誰申請(qǐng),誰釋放
遵循Cocoa Touch的使用原則;
內(nèi)存管理主要要避免“過早釋放”和“內(nèi)存泄漏”,對(duì)于“過早釋放”需要注意@property設(shè)置特性時(shí),一定要用對(duì)特性關(guān)鍵字,對(duì)于“內(nèi)存泄漏”,一定要申請(qǐng)了要負(fù)責(zé)釋放,要細(xì)心。
關(guān)鍵字alloc 或new 生成的對(duì)象需要手動(dòng)釋放;
設(shè)置正確的property屬性,對(duì)于retain需要在合適的地方釋放,
16.What is lazy loading?
懶漢模式,只在用到的時(shí)候才去初始化。也可以理解成延時(shí)加載。我覺得最好也最簡(jiǎn)單的一個(gè)列子就是tableView中圖片的加載顯示了。一個(gè)延時(shí)載,避免內(nèi)存過高,一個(gè)異步加載,避免線程堵塞