1.创建线程
创建线程使用pthread_create
#import "ViewController.h"
#import <pthread/pthread.h>
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//创建子线程
//创建一个线程编号
pthread_t pthread;//线程编号
//第一个参数是线程编号,即线程编号的地址,
//第二个参数是线程属性
//第三个参数指向任何类型的指针,类似于id,但id是指向对象的,这里是c的类型指针,即第三个参数是一个线程要执行的函数
//第四个参数 要执行的函数的参数
//函数的返回值类型为int 0是成功,非零是失败
int result=pthread_create(&pthread, NULL, demo, NULL);
NSLog(@"touchsbegan %@",[NSThread currentThread]);
if (result==0) {
NSLog(@"线程创建成功");
}else{
NSLog(@"线程创建失败");
}
}
//线程执行的函数(c的函数语法),这里需要返回一个地址,因为带*
void *demo(void *param){
NSLog(@"hello world %@",[NSThread currentThread]);
return NULL;
}
@end
效果
2020-07-31 23:41:53.574612+0800 IOS107[6785:387304] touchsbegan <NSThread: 0x6000004b0f40>{number = 1, name = main}
2020-07-31 23:41:53.574751+0800 IOS107[6785:387304] 线程创建成功
2020-07-31 23:41:53.574733+0800 IOS107[6785:387478] hello world <NSThread: 0x6000004fc900>{number = 7, name = (null)}
2.创建线程带参及桥接(__bridge)
#import "ViewController.h"
#import <pthread/pthread.h>
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//创建子线程
//创建一个线程编号
pthread_t pthread;//线程编号
//第一个参数是线程编号,即线程编号的地址,
//第二个参数是线程属性
//第三个参数指向任何类型的指针,类似于id,但id是指向对象的,这里是c的类型指针,即第三个参数是一个线程要执行的函数
//第四个参数 要执行的函数的参数
//函数的返回值类型为int 0是成功,非零是失败
//char *name="zhangsan";
NSString* name=@"zhangsan";
//把oc对象传递给c语言的函数,要桥接
int result=pthread_create(&pthread, NULL, demo, (__bridge void *)name);
NSLog(@"touchsbegan %@",[NSThread currentThread]);
if (result==0) {
NSLog(@"线程创建成功");
}else{
NSLog(@"线程创建失败");
}
}
//线程执行的函数(c的函数语法),这里需要返回一个地址,因为带*
void *demo(void *param){
//使用oc对象的时候也需要桥接一次
NSString* name=(__bridge NSString*)(param);
NSLog(@"hello world %@ %@",param,[NSThread currentThread]);
return NULL;
}
@end
输出结果
2020-07-31 23:56:09.821820+0800 IOS107[6867:395884] touchsbegan <NSThread: 0x600001e9c7c0>{number = 1, name = main}
2020-07-31 23:56:09.821918+0800 IOS107[6867:395884] 线程创建成功
2020-07-31 23:56:09.822003+0800 IOS107[6867:396123] hello world zhangsan <NSThread: 0x600001ecd140>{number = 6, name = (null)}
3.NSSThread创建线程,方法1
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//创建线程对象
//第一个参数是第二个参数方法的对象
//第二个参数是调用的方法
//第三个参数是第二个调用方法的参数
NSThread* thread= [[NSThread alloc] initWithTarget:self selector:@selector(demo) object:nil];
[thread start];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
}
-(void)demo{
NSLog(@"hello %@",[NSThread currentThread]);
}
@end
效果:
2020-08-01 08:51:34.691124+0800 IOS107[934:29400] hello <NSThread: 0x600000ef04c0>{number = 7, name = (null)}
4.NSSThread创建线程,方法2
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//分离新的线程,参数和上例类似
[NSThread detachNewThreadSelector:@selector(demo) toTarget:self withObject:nil];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
}
-(void)demo{
NSLog(@"hello %@",[NSThread currentThread]);
}
@end
效果
2020-08-01 08:58:30.577407+0800 IOS107[970:33890] hello <NSThread: 0x600000fd6d00>{number = 7, name = (null)}
5.NSSThread创建线程,方法3,后台线程
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//后台线程
[self performSelectorInBackground:@selector(demo) withObject:nil];
}
-(void)demo{
NSLog(@"hello %@",[NSThread currentThread]);
}
@end
效果
2020-08-01 09:10:41.063291+0800 IOS107[1009:40653] hello <NSThread: 0x6000039022c0>{number = 8, name = (null)}
6.NSSThread创建线程,方法4,创建线程是传入参数
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//nsthread创建线程的基本方式
NSThread* thread=[[NSThread alloc]initWithTarget:self selector:@selector(demo:) object:@"自定义的线程名称"];
[thread start];
}
-(void)demo:(NSString *)name {
NSLog(@"hello %@",name);
}
@end
效果:
2020-08-01 09:30:11.685584+0800 IOS107[1083:49676] hello 自定义的线程名称
7.线程状态1–就绪,阻塞与死亡
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//新建线程对象
NSThread* thread=[[NSThread alloc]initWithTarget:self selector:@selector(demo) object:nil];
//线程进入就绪状态
[thread start];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
}
-(void)demo{
for (int i=0; i<20; i++) {
NSLog(@"%d",i);
if (i==5) {
//阻塞状态
[NSThread sleepForTimeInterval:4];//阻塞4秒钟
}
if (i==10) {
//线程退出,进入死亡撞他
[NSThread exit];
}
}
}
@end
结果
2020-08-01 09:43:00.861033+0800 IOS107[1180:57748] 0
2020-08-01 09:43:00.861109+0800 IOS107[1180:57748] 1
2020-08-01 09:43:00.861176+0800 IOS107[1180:57748] 2
2020-08-01 09:43:00.861253+0800 IOS107[1180:57748] 3
2020-08-01 09:43:00.861439+0800 IOS107[1180:57748] 4
2020-08-01 09:43:00.861518+0800 IOS107[1180:57748] 5
2020-08-01 09:43:04.864871+0800 IOS107[1180:57748] 6
2020-08-01 09:43:04.865174+0800 IOS107[1180:57748] 7
2020-08-01 09:43:04.865283+0800 IOS107[1180:57748] 8
2020-08-01 09:43:04.865367+0800 IOS107[1180:57748] 9
2020-08-01 09:43:04.865445+0800 IOS107[1180:57748] 10
8.线程状态2–优先级
thread1.threadPriority=10;//优先级数值越大,优先级越高
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//新建线程对象
NSThread* thread1=[[NSThread alloc]initWithTarget:self selector:@selector(demo) object:nil];
//设定线程名字
thread1.name=@"线程一";
//指定线程的 优先级
thread1.threadPriority=10;//优先级数值越大,优先级越高
//线程进入就绪状态
[thread1 start];
//新建线程对象
NSThread* thread2=[[NSThread alloc]initWithTarget:self selector:@selector(demo) object:nil];
//线程进入就绪状态
thread2.name=@"线程二";
thread1.threadPriority=2;//优先级数值越大,优先级越高
[thread2 start];
}
-(void)demo{
for (int i=0; i<20; i++) {
NSLog(@"%d --%@",i,[NSThread currentThread]);
if ([NSThread isMainThread]) {
int n=0;
int m=5/n;
}
//[NSThread sleepForTimeInterval:2];
}
}
@end
9.多线程操作共享资源(线程锁)
#import "ViewController.h"
@interface ViewController ()
@property(nonatomic,assign)int ticketCount;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.ticketCount=10;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//模拟买票窗口一
NSThread* thread1=[[NSThread alloc]initWithTarget:self selector:@selector(sellTickets) object:nil];
thread1.name=@"window1 for ticket";
[thread1 start];
//模拟买票窗口二
NSThread* thread2=[[NSThread alloc]initWithTarget:self selector:@selector(sellTickets) object:nil];
thread2.name=@"window2 for ticket";
[thread2 start];
}
//模拟买票的方法
-(void)sellTickets{
while(YES){
//模拟耗时
[NSThread sleepForTimeInterval:1];
//添加线程锁
@synchronized (self) {//线程同步
if (self.ticketCount>0) {
self.ticketCount--;
NSLog(@"剩余票数为%d张票 %@",self.ticketCount,[NSThread currentThread]);
}else{
NSLog(@"票已经卖完了");
break;
}
}
}
}
@end
效果:
2020-08-01 11:32:22.401243+0800 IOS107[1582:104591] 剩余票数为9张票 <NSThread: 0x6000023fd0c0>{number = 8, name = window1 for ticket}
2020-08-01 11:32:22.401526+0800 IOS107[1582:104592] 剩余票数为8张票 <NSThread: 0x6000023fd040>{number = 9, name = window2 for ticket}
2020-08-01 11:32:23.404197+0800 IOS107[1582:104591] 剩余票数为7张票 <NSThread: 0x6000023fd0c0>{number = 8, name = window1 for ticket}
2020-08-01 11:32:23.404412+0800 IOS107[1582:104592] 剩余票数为6张票 <NSThread: 0x6000023fd040>{number = 9, name = window2 for ticket}
2020-08-01 11:32:24.405751+0800 IOS107[1582:104591] 剩余票数为5张票 <NSThread: 0x6000023fd0c0>{number = 8, name = window1 for ticket}
2020-08-01 11:32:24.405925+0800 IOS107[1582:104592] 剩余票数为4张票 <NSThread: 0x6000023fd040>{number = 9, name = window2 for ticket}
2020-08-01 11:32:25.410800+0800 IOS107[1582:104591] 剩余票数为3张票 <NSThread: 0x6000023fd0c0>{number = 8, name = window1 for ticket}
2020-08-01 11:32:25.411119+0800 IOS107[1582:104592] 剩余票数为2张票 <NSThread: 0x6000023fd040>{number = 9, name = window2 for ticket}
2020-08-01 11:32:26.412395+0800 IOS107[1582:104591] 剩余票数为1张票 <NSThread: 0x6000023fd0c0>{number = 8, name = window1 for ticket}
2020-08-01 11:32:26.415721+0800 IOS107[1582:104592] 剩余票数为0张票 <NSThread: 0x6000023fd040>{number = 9, name = window2 for ticket}
2020-08-01 11:32:27.415349+0800 IOS107[1582:104591] 票已经卖完了
2020-08-01 11:32:27.419348+0800 IOS107[1582:104592] 票已经卖完了
2020-08-01 11:33:35.305842+0800 IOS107[1582:105533] 票已经卖完了
2020-08-01 11:33:35.306078+0800 IOS107[1582:105532] 票已经卖完了
2020-08-01 11:33:36.123909+0800 IOS107[1582:105544] 票已经卖完了
2020-08-01 11:33:36.124134+0800 IOS107[1582:105545] 票已经卖完了
10.开启多线程异步下载网络图片
#import "ViewController.h"
@interface ViewController ()
@property(nonatomic,strong)UIScrollView* scrollView;
@property(nonatomic,strong)UIImageView* imageView;
@end
@implementation ViewController
//加载视图
-(void)loadView{
self.scrollView=[[UIScrollView alloc]initWithFrame:[UIScreen mainScreen].bounds];
self.scrollView.backgroundColor=[UIColor whiteColor];
self.view=self.scrollView;
self.imageView=[[UIImageView alloc]init];
[self.scrollView addSubview:self.imageView];
}
- (void)viewDidLoad {
[super viewDidLoad];
//创建线程,注意,这里线程操作了UI主线程
NSThread* thread=[[NSThread alloc]initWithTarget:self selector:@selector(downloadImage) object:nil];
[thread start];
[self downloadImage];
}
//下载网路图片的方法
-(void)downloadImage{
//创建一个url地址
NSURL* url=[NSURL URLWithString:@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1596266796912&di=2b160825f46fe50a328bba978e6d385c&imgtype=0&src=http%3A%2F%2F01.minipic.eastday.com%2F20170421%2F20170421143734_ba2eace48dd7194f8c64d545ad7c50ca_8.jpeg"];
//下载图片
NSData* data=[NSData dataWithContentsOfURL:url];
//二进制数据转化为图片
UIImage* image=[UIImage imageWithData:data];
//操作了UI主线程,一定要去主线程上更新UI控件。线程间通信
//第三个参数waitUntilDone值是YES会等待方法执行完毕,才会执行后续代码
[self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];
}
//更新UI操作界面
-(void)updateUI:(UIImage*)image{
//将图片添加到self.imageview上
self.imageView.image=image;
//让imageview和内容大小保持一致
[self.imageView
sizeToFit ];
//让scrollview滚动起来
self.scrollView.contentSize=image.size;
}
@end
效果:
11.关于属性
属性包括:
retain
strong
weak
assign分配
copy
字符串一般是用 copy
block作为属性的时候使用 copy
delegate用weak修饰
bool,数值等使用assign
arc下才能用weak
mrc下使用retain
拖线一般使用weak