多线程基础-实例操作

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;

            }

        }

    }

    

}


以上是关于多线程基础-实例操作的主要内容,如果未能解决你的问题,请参考以下文章

Java高并发-多线程基础

C#基础知识学习之 ☀️ | 多线程的使用基础

多线程基础-C#

多线程学习一(多线程基础)

java核心技术-多线程基础

Java多线程基础