xcode吧 关注:8,390贴子:34,069
  • 13回复贴,共1

关于iOS多线程,说的很详细你会懂会懂!

只看楼主收藏回复


事出必有因,今天我想和你聊聊线程的原因就是——当然是本着一个共产党人的思想觉悟,为人民透析生命,讲解你正在蒙圈的知识点,或者想破脑袋才发现如此简单的技术方案。


1楼2017-12-21 22:01回复

    很多人学线程,迷迷糊糊;很多人问线程,有所期待;也有很多人写线程,分享认知给正在努力的年轻人,呦,呦,呦呦。但是,你真的了解线程么?你真的会用多线程么?你真的学明白,问明白,写明白了么?不管你明不明白,反正我不明白,但是,没准,你看完,你就明白了。


    2楼2017-12-21 22:02
    回复
      2026-01-22 19:14:26
      广告
      不感兴趣
      开通SVIP免广告


      3楼2017-12-21 22:02
      回复
        前言
        提到线程,那就不得不提CPU,现代的CPU有一个很重要的特性,就是时间片,每一个获得CPU的任务只能运行一个时间片规定的时间。
        其实线程对操作系统来说就是一段代码以及运行时数据。操作系统会为每个线程保存相关的数据,当接收到来自CPU的时间片中断事件时,就会按一定规则从这些线程中选择一个,恢复它的运行时数据,这样CPU就可以继续执行这个线程了。
        也就是其实就单核CUP而言,并没有办法实现真正意义上的并发执行,只是CPU快速地在多条线程之间调度,CPU调度线程的时间足够快,就造成了多线程并发执行的假象。并且就单核CPU而言多线程可以解决线程阻塞的问题,但是其本身运行效率并没有提高,多CPU的并行运算才真正解决了运行效率问题。
        系统中正在运行的每一个应用程序都是一个进程,每个进程系统都会分配给它独立的内存运行。也就是说,在iOS系统中中,每一个应用都是一个进程。
        一个进程的所有任务都在线程中进行,因此每个进程至少要有一个线程,也就是主线程。那多线程其实就是一个进程开启多条线程,让所有任务并发执行。
        多线程在一定意义上实现了进程内的资源共享,以及效率的提升。同时,在一定程度上相对独立,它是程序执行流的最小单元,是进程中的一个实体,是执行程序最基本的单元,有自己栈和寄存器。
        上面这些你是不是都知道,但是我偏要说,哦呵呵。既然我们聊线程,那我们就先从线程开刀。


        4楼2017-12-21 22:02
        回复
          Pthreads && NSThread
          先来看与线程有最直接关系的一套C的API:


          5楼2017-12-21 22:03
          回复
            Pthreads
            POSIX线程(POSIX threads),简称Pthreads,是线程的POSIX标准。该标准定义了创建和操纵线程的一整套API。在类Unix操作系统(Unix、Linux、Mac OS X等)中,都使用Pthreads作为操作系统的线程。


            6楼2017-12-21 22:03
            回复
              一起学习iOS开发

              加入我们吧


              9楼2017-12-21 22:21
              回复
                呃,七八楼发代码截图被删了,不发图了,代码丑点就丑点吧


                10楼2017-12-21 22:23
                回复
                  2026-01-22 19:08:26
                  广告
                  不感兴趣
                  开通SVIP免广告
                  补七楼:
                  高大上有木有,跨平台有木有,你没用过有木有!下面我们来看一下这个看似**但真的基本用不到的Pthreads是怎么用的:
                  不如我们来用Pthreads创建一个线程去执行一个任务:
                  记得引入头文件`#import "pthread.h"`
                  -(void)pthreadsDoTask{ /* pthread_t:线程指针 pthread_attr_t:线程属性 pthread_mutex_t:互斥对象 pthread_mutexattr_t:互斥属性对象 pthread_cond_t:条件变量 pthread_condattr_t:条件属性对象 pthread_key_t:线程数据键 pthread_rwlock_t:读写锁 // pthread_create():创建一个线程 pthread_exit():终止当前线程 pthread_cancel():中断另外一个线程的运行 pthread_join():阻塞当前的线程,直到另外一个线程运行结束 pthread_attr_init():初始化线程的属性 pthread_attr_setdetachstate():设置脱离状态的属性(决定这个线程在终止时是否可以被结合) pthread_attr_getdetachstate():获取脱离状态的属性 pthread_attr_destroy():删除线程的属性 pthread_kill():向线程发送一个信号 pthread_equal(): 对两个线程的线程标识号进行比较 pthread_detach(): 分离线程 pthread_self(): 查询线程自身线程标识号 // *创建线程 int pthread_create(pthread_t _Nullable * _Nonnull __restrict, //指向新建线程标识符的指针 const pthread_attr_t * _Nullable __restrict, //设置线程属性。默认值NULL。 void * _Nullable (* _Nonnull)(void * _Nullable), //该线程运行函数的地址 void * _Nullable __restrict); //运行函数所需的参数 *返回值: *若线程创建成功,则返回0 *若线程创建失败,则返回出错编号 */ // pthread_t thread = NULL; NSString *params = @"Hello World"; int result = pthread_create(&thread, NULL, threadTask, (__bridge void *)(params)); result == 0 ? NSLog(@"creat thread success") : NSLog(@"creat thread failure"); //设置子线程的状态设置为detached,则该线程运行结束后会自动释放所有资源 pthread_detach(thread);}void *threadTask(void *params) { NSLog(@"%@ - %@", [NSThread currentThread], (__bridge NSString *)(params)); return NULL;}


                  11楼2017-12-21 22:24
                  回复
                    NSThread
                    哎呀,它面向对象,再去看看苹果提供的API,对比一下Pthreads,简单明了,人生仿佛又充满了阳光和希望,我们先来一看一下系统提供给我们的API自然就知道怎么用了,来来来,我给你注释一下啊:
                    @interface NSThread : NSObject
                    //当前线程
                    @property (class, readonly, strong) NSThread *currentThread;
                    //使用类方法创建线程执行任务
                    + (void)detachNewThreadWithBlock:(void (^)(void))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
                    + (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument;
                    //判断当前是否为多线程
                    + (BOOL)isMultiThreaded;
                    //指定线程的线程参数,例如设置当前线程的断言处理器。@property (readonly, retain) NSMutableDictionary *threadDictionary;
                    //当前线程暂停到某个时间
                    + (void)sleepUntilDate:(NSDate *)date;
                    //当前线程暂停一段时间
                    + (void)sleepForTimeInterval:(NSTimeInterval)ti;
                    //退出当前线程
                    + (void)exit;
                    //当前线程优先级
                    + (double)threadPriority;
                    //设置当前线程优先级
                    + (BOOL)setThreadPriority:(double)p;
                    //指定线程对象优先级 0.0~1.0,默认值为0.5
                    @property double threadPriority NS_AVAILABLE(10_6, 4_0);
                    //服务质量
                    @property NSQualityOfService qualityOfService NS_AVAILABLE(10_10, 8_0);
                    //线程名称
                    @property (nullable, copy) NSString *name NS_AVAILABLE(10_5, 2_0);
                    //栈区大小
                    @property NSUInteger stackSize NS_AVAILABLE(10_5, 2_0);
                    //是否为主线程@property (class, readonly) BOOL isMainThread NS_AVAILABLE(10_5, 2_0);
                    //获取主线程@property (class, readonly, strong) NSThread *mainThread NS_AVAILABLE(10_5, 2_0);
                    //初始化- (instancetype)init NS_AVAILABLE(10_5, 2_0) NS_DESIGNATED_INITIALIZER;
                    //实例方法初始化,需要再调用start方法
                    - (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(nullable id)argument NS_AVAILABLE(10_5, 2_0);
                    - (instancetype)initWithBlock:(void (^)(void))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
                    //线程状态,正在执行
                    @property (readonly, getter=isExecuting) BOOL executing NS_AVAILABLE(10_5, 2_0);
                    //线程状态,正在完成
                    @property (readonly, getter=isFinished) BOOL finished NS_AVAILABLE(10_5, 2_0);
                    //线程状态,已经取消
                    @property (readonly, getter=isCancelled) BOOL cancelled NS_AVAILABLE(10_5, 2_0);
                    //取消,仅仅改变线程状态,并不能像exist一样真正的终止线程
                    - (void)cancel NS_AVAILABLE(10_5, 2_0);
                    //开始- (void)start NS_AVAILABLE(10_5, 2_0);
                    //线程需要执行的代码,一般写子类的时候会用到- (void)main NS_AVAILABLE(10_5, 2_0);
                    @end另外,还有一个NSObject的分类,瞅一眼:
                    @interface NSObject (NSThreadPerformAdditions)
                    //隐式的创建并启动线程,并在指定的线程(主线程或子线程)上执行方法。
                    - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray *)array;
                    - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait;
                    - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray *)array NS_AVAILABLE(10_5, 2_0);
                    - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait NS_AVAILABLE(10_5, 2_0);
                    - (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg NS_AVAILABLE(10_5, 2_0);
                    @end


                    14楼2017-12-21 22:30
                    回复
                      上面的介绍您还满意吗?小的帮您下载一张图片,您瞧好:
                      -(void)creatBigImageView{ self.bigImageView = [[UIImageView alloc] initWithFrame:self.view.bounds]; [self.view addSubview:_bigImageView]; UIButton *startButton = [UIButton buttonWithType:UIButtonTypeSystem]; startButton.frame = CGRectMake(0, 0, self.view.frame.size.width / 2, 50); startButton.backgroundColor = [UIColor grayColor]; [startButton setTitle:@"开始加载" forState:UIControlStateNormal]; [startButton addTarget:self action:@selector(loadImage) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:startButton]; UIButton *jamButton = [UIButton buttonWithType:UIButtonTypeSystem]; jamButton.frame = CGRectMake(self.view.frame.size.width / 2, 0, self.view.frame.size.width / 2, 50); jamButton.backgroundColor = [UIColor grayColor]; [jamButton setTitle:@"阻塞测试" forState:UIControlStateNormal]; [jamButton addTarget:self action:@selector(jamTest) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:jamButton];}-(void)jamTest{ UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"线程阻塞" message:@"" delegate:nil cancelButtonTitle:@"好" otherButtonTitles:nil, nil]; [alertView show];}-(void)loadImage{ NSURL *imageUrl = [NSURL URLWithString:@"
                      "]; NSData *imageData = [NSData dataWithContentsOfURL:imageUrl]; [self updateImageData:imageData];}-(void)updateImageData:(NSData*)imageData{ UIImage *image = [UIImage imageWithData:imageData]; self.bigImageView.image = image;}


                      15楼2017-12-21 22:31
                      收起回复
                        补充8楼的也被删了。。。
                        也没人回帖
                        算了,
                        不发了有人回复我我再继续发,累死了


                        16楼2017-12-21 22:36
                        回复
                          小白看不懂


                          IP属地:日本来自iPhone客户端19楼2018-03-28 07:40
                          回复