线程死锁:当线程访问一个资源时,如果该资源已经被其他进程正在访问(已加锁),如果想要使用该资源,必须等其他资源解锁完毕,如果不解锁,线程处于长期等待状态.
线程互斥:当多个线程访问同一块资源时,为了保证访问安全,一个线程在访问时,其他线程处于等待状态.
线程同步:线程之间存在依赖关系,后一个线程的执行必须依赖于前一个任务的结束.
线程并发:线程与线程之间不存在依赖关系,同时执行,可能后分配的线程的任务先完成.
子线程完成耗时操作,主线程负责界面显示
队列为每一个任务分配了一个子线程,因为队列是先进先出,所以分配任务时有先后顺序,但是所有任务又是同时进行(线程并发).
任务队列创建的线程数量有系统性能决定,但是能够保证所有的任务君子爱子线程中执行.
网络中的同步连接和异步连接
:
属于连接方式
,
请求线程不同
:
同步连接网络请求是由主线程处理
,
而异步连接是由子线程处理
.
线程同步和线程并发
:
属于多线程之间的关系
.
线程同步
:
各线程执行的任务之间存在依赖关系
,
后一个线程执行任务必须等待前一个线程执行任务结束
.
线程并发
:
线程同时执行任务
,
线程执行的任务之间没有依赖关系
,
可能后执行任务的线程先完成任务
.
主线程和子线程都可以实现线程同步
,
但是只有子线程能够实现线程并发
.
@interface
AppDelegate
()
{
NSInteger
_totalTickets;
//
剩余票数
NSLock
*_lock;
//
存储加锁对象
}
@end
@implementation
AppDelegate
- (
void
)test1:(
NSString
*)name {
//
子线程中没有自动释放池
NSLog
(
@"fan test1 = %@, isMainThread = %d"
,[
NSThread
currentThread
],[[
NSThread
currentThread
]
isMainThread
]);
for (int i = 0; i < 10; i++) {
NSLog(@"%d", i);
}
//
定时器在主线程中能够响应对应的方法
,
但是在子线程中不能
.
//
原因
:
主线程在
UIApplicationMain
函数中开启了事件循环
,
能够及时捕获操作
,
及时处理
,
但是在子线程中并没有开启事件循环
.
@autoreleasepool
{
[
NSTimer
scheduledTimerWithTimeInterval
:
1
target
:
self
selector
:
@selector
(aa)
userInfo
:
nil
repeats
:
YES
];
//
获取当前线程中的事件循环
NSRunLoop
*loop = [
NSRunLoop
currentRunLoop
];
//
开启事件循环
.
[loop
run
];
}
}
- (
void
)aa {
NSLog
(
@"lanou"
);
}
- (
void
)test2 {
NSLog
(
@"fan test2 = %@, isMainThread = %d"
,[
NSThread
currentThread
],[[
NSThread
currentThread
]
isMainThread
]);
for
(
int
i =
0
; i<
1000
; i++) {
NSLog
(
@"Duck is duck"
);
}
}
- (
void
)sellTicket:(
NSString
*)name {
线程互斥
:
当多个线程访问同一块资源时
,
为了保证访问安全
,
一个线程在访问时
,
其他线程处于等待状态
.
线程死锁
:
当线程访问一个资源时
,
如果该资源已经被其他线程正在访问
(
已加锁
),
如果想要使用该资源
,
必须等其他线程解锁完毕
,
如果不解锁
,
线程处于长期等待状态
.
@autoreleasepool
{
while
(
YES
) {
[
_lock
lock
];
//
加锁
.
if
(
_totalTickets
>
0
) {
_totalTickets
--;
NSLog
(
@"%@
剩余票数为
%d"
, name,
_totalTickets
);
}
else
{
NSLog
(
@"%@
票已卖完
"
, name);
break
;
}
//[_lock unlock]; //
解锁
}
}
}
- (
BOOL
)application:(
UIApplication
*)application didFinishLaunchingWithOptions:(
NSDictionary
*)launchOptions {
self
.
window
= [[
UIWindow
alloc
]
initWithFrame
:[[
UIScreen
mainScreen
]
bounds
]];
[
_window
release
];
//
主线程中
//
创建子线程
,
完成
test1
操作
//
子线程完成耗时操作
,
主线程负责界面显示
.
//1.
创建子线程的方式
,
使用
NSThread
创建线程
// [NSThread detachNewThreadSelector:@selector(test1) toTarget:self withObject:nil];
//2.
创建子线程方式
,
使用
NSTread
添加线程任务
.
// NSThread *tread = [[NSThread alloc] initWithTarget:self selector:@selector(test1) object:nil];
// [tread start]; //
执行任务
,
此时才会开辟子线程
//3.
创建子线程方式
,
将任务添加到
NSOperationQueue(
任务队列
,
先进先出
)
中
,
由队列针对于所有的任务合理的分配线程
.
// NSInvocationOperation *operation1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(test1) object:self];
// NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(test2) object:self];
//
添加到任务队列中
//
队列为每一任务分配了一个子线程
,
因为队列是先进先出
,
所以分配任务时有先后顺序
,
但是所有任务又是同时进行
(
线程并发
),
//
线程同步
:
线程之间存在依赖关系
,
后一个线程的执行必须依赖于前一个任务的结束
.
//
线程并发
:
线程与线程之间不存在依赖关系
,
同时执行
,
可能后分配的线程的任务先完成
.
//
任务队列创建的线程数量由系统性能决定
.
但是能够保证所有的任务均在子线程中执行
.
//NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//
设置最大并发数
,
同一时间允许执行的任务数
.
//[queue setMaxConcurrentOperationCount:1];
//
添加任务之间的依赖关系
//[operation2 addDependency:operation1];
//[queue addOperation:operation1];
//[queue addOperation:operation2];
//[operation1 release];
//[operation2 release];
//[queue release];
//4.
使用
NSObject
分类中提供了创建子线程的方法
//[self performSelectorInBackground:@selector(test1:) withObject:@"fgj"];
// _totalTickets = 30; //
剩余票数
// _lock = [[NSLock alloc] init];
//
模拟售票
// [NSThread detachNewThreadSelector:@selector(sellTicket:) toTarget:self withObject:@"chao"];
// [NSThread detachNewThreadSelector:@selector(sellTicket:) toTarget:self withObject:@"qing"];
UIImageView
*imageView = [[
UIImageView
alloc
]
initWithFrame
:
self
.
window
.
bounds
];
imageView.
backgroundColor
= [
UIColor
yellowColor
];
imageView.
tag
=
100
;
[
self
.
window
addSubview
:imageView];
[imageView
release
];
//
类似于网络请求等耗时操作
,
交有子线程去处理
.
[
self
performSelectorInBackground
:
@selector
(downLoadImage)
withObject
:
nil
];
self
.
window
.
backgroundColor
= [
UIColor
redColor
];
[
self
.
window
makeKeyAndVisible
];
return
YES
;
}
- (
void
)downLoadImage {
NSLog
(
@"%@, isMainThread = %d"
,[
NSThread
currentThread
],[[
NSThread
currentThread
]
isMainThread
]);
UIImage
*image = [
UIImage
imageWithData
:[
NSData
dataWithContentsOfURL
:[
NSURL
URLWithString
:
@"
http://image.zcool.com.cn/56/13/1308200901454.jpg
"
]]];
//
刷新
UI
界面的操作交由主线程去处理
.
//
从子线程中跳到主线程中
,
处理
UI
[
self
performSelectorOnMainThread
:
@selector
(loadImage:)
withObject
:image
waitUntilDone
:
YES
];
}
- (
void
)loadImage:(
UIImage
*)image {
NSLog
(
@"%@"
,[
NSThread
currentThread
]);
UIImageView
*imageView = (
UIImageView
*)[
self
.
window
viewWithTag
:
100
];
imageView.
image
= image;
}