多线程基础-实例操作
Posted 程序员之最
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程基础-实例操作相关的知识,希望对你有一定的参考价值。
1:耗时操作
/*
[NSThread currentThread] 查看当前线程
通常用来在多线程开发中,判断是否在主线程
number == 1 说明是在主线程
number != 1 说明是在子线程
*/
-(void)longOperation
{
for (int i = 0; i < 50000; i++) {
//NSLog 是专门用来调试的,性能非常不好,在上架的时候,全部要去掉~
NSLog(@"%d %@",i,[NSThread currentThread]);
}
}
2:c语言pthread介绍
#import <pthread.h> //POSIX 多线程开发框架
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
#pragma mark - <演练pthread>
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self pthreadDemo];
}
/*
参数:
返回值:- 如果是 0, 表示正确 - 如果是非0,表示错误码
void * -- (*) -- (void *)
返回值 -- (函数指针) -- (参数)
void * 相当于 OC中的id
*/
-(void)pthreadDemo{
pthread_t threadID;
NSString * str = @"hello 老王";
/*
- 在 ARC 开发中, 如果遇到 OC和C 语言中相同数据类型进行转换,需要使用__bridge "桥接"
- 在 MRC 开发中,不需要桥接
在 OC 中,如果是ARC开发,编译器会在编译的时候,自动根据代码结构,添加 retain , release, autorelease
ARC 只负责 OC部分的代码,不负责C的代码. 如果C的代码里面出现了 retain/create/copy 字样的函数,都需要release
*/
int result = pthread_create(&threadID, NULL, &demo, (__bridge void *)(str));
if (result == 0) {
for (int i = 0; i < 20; i++) {
NSLog(@"OK!");
}
}else{
NSLog(@"error %d",result);
}
}
void * demo(void *param){
NSString * sss = (__bridge NSString *)(param);
NSLog(@"%@---%@",[NSThread currentThread],sss);
return NULL;
}
3:NSThread使用
- (void)creatNSThread{// 主线程
NSLog(@"A---------");
// 创建一个 主线程 NSThread
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadDemo:) object:@"Thread"];
// 启动线程
[thread start];
for (int i = 0; i < 10; i ++) {
NSLog(@"----i--%d",i);
}
NSLog(@"B---------");
}
- (void)threadDemo2{// 主线程
NSLog(@"A--------%@-",[NSThread currentThread]);
// detach ==> 分离一个 子线程 不需要start 不需要创建
[NSThread detachNewThreadSelector:@selector(threadDemo:) toTarget:self withObject:@"Thread"];
NSLog(@"B--------%@-",[NSThread currentThread]);
}
- (void)threadDemo3{
NSLog(@"A--------%@-",[NSThread currentThread]);
//InBackground 就在子线程执行(后台运行)
//是NSobject的分类 意味着所有继承NSobject 的类都可以使用
// 使用方便 不需要 NSThread
[self performSelectorInBackground:@selector(threadDemo:) withObject:@"Thread"];
NSLog(@"B--------%@-",[NSThread currentThread]);
// 主线程
}
- (void)threadDemo:(id)obj{//子线程
for (int i = 0; i < 2 ; i ++) {
NSLog(@"C----%@",[NSThread currentThread]);
}
}
4: NSThread状态
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
NSLog(@" 走起 ");
// 杀主线程 exit 没法杀掉主线程 杀掉主线程 后续的所有代码都不会执行,App不会挂掉
// [NSThread exit];
[self threadDemo];
}
- (void)exitDemo{
[self performSelectorInBackground:@selector(starMainThread) withObject:nil];
[NSThread exit];
}
- (void)starMainThread{
[NSThread sleepForTimeInterval:1.0];
[[NSThread mainThread] start];
NSLog(@"重新开启主线程了吗");
}
- (void)threadDemo{
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadState:) object:@"Thread"];
// 线程就绪
[thread start];
}
- (void)threadState:(id)obj{
//阻塞,当运行满足某个条件,就会让线程“休眠一会”
// sleep 方法是类方法 ,会直接休眠当前线程!!
// NSLog(@"休眠一会");
// [NSThread sleepForTimeInterval:2.0];
for (int i = 0; i < 20; i ++) {
if (i == 6) {
NSLog(@"休眠一会");
[NSThread sleepForTimeInterval:2.0];
}
NSLog(@"%@ --%d",[NSThread currentThread],i);
// 当线程满足某一个条件时 ,可以强行终止的
// exit 类方法 可以强行终止当前线程
if (i == 12) {
// 一旦强行终止线程,后续的所有代码都不会执行。
// 注意:在线程终止之前,应该释放之前分配的对象
[NSThread exit];
}
//线程 执行完毕,或则强行退出或则异常,三种情况线程就会死亡。
}
NSLog(@"睡醒了");
}
5:NSThread 的属性:
-(void)threadDemo{
NSThread * t1 = [[NSThread alloc]initWithTarget:self selector:@selector(demo) object:nil];
// 在大型项目中,通常希望程序崩溃的时候,能够获取到准确的线程,就需要给每个线程取一个名字!
t1.name = @"Thread A";
//优先级
t1.threadPriority = 1.0;
[t1 start];
NSThread * t2 = [[NSThread alloc]initWithTarget:self selector:@selector(demo) object:nil];
// 在大型项目中,通常希望程序崩溃的时候,能够获取到准确的线程,就需要给每个线程取一个名字!
t2.name = @"Thread B";
/*优先级
* 优先级只能保证 CPU 调度的可能性会高!
* 多线程的目的: 将耗时的操作放在后台,不阻塞主线程和用户的交互!
* 建议: 尽量不要修改 优先级!
* "优先级翻转"
* 在多线程开发中,不要相信你看到的结果!!一定要理性的(冷静)分析!!
*/
t2.threadPriority = 0.1;
[t2 start];
}
-(void)demo{
for (int i = 0; i < 10 ; i ++) {
NSLog(@"%@--%d",[NSThread currentThread],i);
}
}
6:资源共享NSThread处理
/** 票 */
@property(assign,nonatomic)int tickets;
/** 锁 */
@property(nonatomic,strong)NSObject * lockObjc;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.lockObjc = [[NSObject alloc]init];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
self.tickets = 20;
NSThread * t1 = [[NSThread alloc]initWithTarget:self selector:@selector(saleTickets) object:nil];
t1.name = @"售票员 A";
[t1 start];
NSThread * t2 = [[NSThread alloc]initWithTarget:self selector:@selector(saleTickets) object:nil];
t2.name = @"售票员 B";
[t2 start];
}
-(void)saleTickets{
while (YES) {
//0.买票要1秒钟
[NSThread sleepForTimeInterval:1.0];
//参数:就是能够加锁的任意 NSOjbect 对象
//局部变量: 每个线程单独拥有的,无法锁住!!
//注意: 锁一定要是所有线程共享的对象!!
// NSObject * lockObj = [[NSObject alloc]init];
@synchronized (self.lockObjc) {
//互斥锁 - 保证锁内的代码,同一时间,只有一条线程能够执行!!
//互斥锁它的范围,应该尽量小,锁范围越大,效率越低!
//1.还有没有票
if (self.tickets > 0) {
//2.卖出一张票
self.tickets --;
NSLog(@"剩下 %d 张票 --- %@",self.tickets,[NSThread currentThread]);
}else{
NSLog(@"没有票了 %@",[NSThread currentThread]);
break;
}
}
}
}
以上是关于多线程基础-实例操作的主要内容,如果未能解决你的问题,请参考以下文章