iOS中NSThread(主线程,子线程)

#import "AppDelegate.h"

@interface AppDelegate ()
{
    NSInteger _totalTickests;
}
@property (nonatomic, retain) NSLock *lock;
@end

@implementation AppDelegate
- (void)task1 {

    NSLog(@"当前线程:%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);
    //当前任务在主线程中完成,未完成之前不会执行后面的代码
    for (long i = 0; i <= 10000000; i++) {
        NSLog(@"%ld",i);
    }
}

- (void)task2 {

    NSLog(@"当前线程:%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);
    //当前任务在主线程中完成,未完成之前不会执行后面的代码
    for (long i = 0; i <= 100; i++) {
        NSLog(@"我是啦啦啦");
    }
}

- (void)task3{
    NSLog(@"嘎嘎嘎嘎嘎");
}
- (void)task4{
    NSLog(@"蓝欧4");
}
- (void)task5{
    NSLog(@"iOS5");
}

/**
 *  系统默认在主线程中开启事件循环,不断地监听用户交互事件,但在子线程中没有开启时事件循环. runloop
 */
- (void)startTime{
    @autoreleasepool {
        //开启定时器
        [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(task3) userInfo:nil repeats:YES];
        //在子线程中开启事件循环,正是有了事件循环,定时器才能够重复的执行任务.
        [[NSRunLoop currentRunLoop] run];
    }
}
/*
 程序:安装在移动设备上得每个应用,都是一个程序
 进程:正在运行的每一个应用程序就是一个进程,进程相当于一个任务.
 线程:执行任务的单元片段叫做线程,也就是任务的真正执行者,只不过系统默认的把任务交给一个线程来做,则个线程就是主线程,为了提高用户体验,我们需要把耗时的操作交给子线程来做.

 */
//买票
- (void)sellTickets:(NSString *)name{
    @autoreleasepool {
        while(YES){
            [self.lock lock];
            if (_totalTickests > 0) {
                //买票
                _totalTickests--;
                NSLog(@"%@卖得票,剩余票数%ld张",name, _totalTickests);

            }else{
                NSLog(@"%@卖完了",name);
                break;
            }
            [self.lock unlock];
        }
    }
}

//线程死锁:临界资源减少解锁的过程,就容易造成死锁,一个线程等待另一个线程释放资源,但是,前一个线程缺少解锁过程,造成后一个线程一直处于等待状态
//线程互斥:当多个线程访问同一资源,一个线程访问,其他线程应该等待,此时需要加锁

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];

    //NSLog(@"当前线程:%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);

    //初始化票数
    _totalTickests = 30;
    //创建锁

    self.lock = [[[NSLock alloc] init] autorelease];

    //窗口1
    [NSThread detachNewThreadSelector:@selector(sellTickets:) toTarget:self withObject:@"张好好"];
    //窗口2

     [NSThread detachNewThreadSelector:@selector(sellTickets:) toTarget:self withObject:@"金凤"];

    //[self task1];

    //对于耗时的操作,交由子线程来完成,主线程依旧可以来处理用户交互和界面的变化

    //1.创建子线程第一种方式,使用线程类 NSThread
    //[NSThread detachNewThreadSelector:@selector(task1) toTarget:self withObject:nil];

    //2.创建子线程第二种方式,使用线程类,需要手动开启
//    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(task1) object:nil];
//
//    [thread start]; //开启线程
//
//    //释放
//    [thread release];

    //3.创建子线程第三种方式,使用NSObject 提供的方法
    //[self performSelectorInBackground:@selector(downloadImage) withObject:nil];
    //主线程定时器
    //[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(task3) userInfo:nil repeats:YES];
    //创建子线程,开启定时器
    //[self performSelectorInBackground:@selector(startTime) withObject:nil];

//    UIImageView *imageView = [[UIImageView alloc] initWithFrame:[UIScreen mainScreen].bounds];
//    imageView.tag = 100;
//    imageView.backgroundColor = [UIColor cyanColor];
//    [self.window addSubview:imageView] ;
//    [imageView release];

    //4.创建子线程第四种方式,创建爱你任务队列,任务对列会为队列中的任务,合理安排子线程来完成任务.
    //创建任务1
    //NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task4) object:nil];
   // NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task5) object:nil];
    //创建任务2
//    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
//        for (int i = 0; i < 10; i++) {
//            NSLog(@"Frank is ....");
//        }
//    }];
//
//    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
//        for (int i = 0; i < 10; i++) {
//            NSLog(@"你说啥..");
//        }
//    }];
    //创建任务队列,将任务添加到任务队列中
    //NSOperationQueue *quene = [[NSOperationQueue alloc] init];
//    //1.实现线程同步第一种方式,设置最大的并发数
//    [quene setMaxConcurrentOperationCount:1];
    //2.实现线程同步的第二种方式,添加依赖关系
    //[op2 addDependency:op1];

    //[quene addOperation:op1];
    //[quene addOperation:op2];

    //释放
    //[op1 release];
    //[op2 release];
    //[quene release];

    self.window.backgroundColor = [UIColor redColor];
    [self.window makeKeyAndVisible];
    return YES;
}
/**
 *  线程同步:
 线程并发:任务与任务之间没有先后关系,先执行的线程,有可能是最后一个完成的任务.
 */

/**
 主线程跳转到子线程执行任务: 直接创建子线程, 执行对应的耗时的任务即可
 子线程跳转到主线程执行任务: 对于界面的刷新操作, 交由主线程操作, 使用performSelectorOnMainThread::: 操作
 */

//下载图片
- (void)downloadImage{

    //子线程没有自动释放池,遍历构造器内部操作是autorelease来管理内存,因此需要自己添加自动释放池

    @autoreleasepool {
         [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(task3) userInfo:nil repeats:YES];

        //Get请求,同步连接
        //1.创建网址字符串对象
        NSString *str = @"http://image.zcool.com.cn/56/13/1308200901454.jpg";
        //2.创建NSURL对象
        NSURL *url = [NSURL URLWithString:str];
        //3.创建请求对象
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        //4.连接
        NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
        UIImage *image = [UIImage imageWithData:data];

        //如果要刷新UI(界面),修改界面,应该交由主线程处理
        //子线程跳转到主线程中,执行任务
        [self performSelectorOnMainThread:@selector(referenceUI:) withObject:image waitUntilDone:YES];
        //waitUntilDone :是否等待完成
        //如果多个参数,可以将多个参数放入字典或者数组中,withObject:给字典或者数组即可

    }

}
- (void)referenceUI:(UIImage *)image{
    UIImageView *imageView = (UIImageView *)[self.window viewWithTag:100];
    imageView.image = image;
}

- (void)dealloc{
    self.window = nil;
    self.lock = nil;
    [super dealloc];
}
@end
时间: 2024-10-11 16:51:17

iOS中NSThread(主线程,子线程)的相关文章

在C#中主线程和子线程如何实现互相传递数据

在C#中主线程和子线程如何实现互相传递数据 老帅 在C#中创建线程Thread时,可以有多种方法,而主线程和子线程之间又如何实现互相传递数据,每种创建方法传递参数的效果是不同的,逐一看一下:  一.不带参数创建Thread 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 using System;  using System.Collections.Generic;  using System.Text;  using Sy

Android中Toast如何在子线程中调用

当我们在应用的子线程中调用Toast的时候,我们会发现编译时并没有问题,但是当我们运行时就会出现如下错误 大专栏  Android中Toast如何在子线程中调用l/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="image"/> 通常我们都会认为此问题是因为在子线程中去更新UI导致的,其实不然,因为我们观察所抛出的log信息即可发现不是更新UI导致的,那么是什么原因导致的此问题呢 原文地址:https://www.cnblog

按键精灵 用全局变量控制线程 子线程控制主线

//************************************************用全局变量控制线程 子线程控制主线 Global b b = 1 线程控制ID = BeginThread(线程控制)//启动线程 While b=1 Delay 2000 Call Plugin.Msg.Tips("我是主线程") wend Rem aaa Delay 8000 While b=2 Delay 2000 Call Plugin.Msg.Tips("我是主线程副

iOS 多线程 NSThread NSOperation NSOperationQueue GCD 线程锁 线程阻塞

iPhone中的线程应用并不是无节制的,官方给出的资料显示,iPhone OS下的主线程的堆栈大小是1M,第二个线程开始就是512KB,并且该值不能通过编译器开关或线程API函数来更改,只有主线程有直接修改UI的能力,所以一些数据层面可以开辟线程来操作进行,iOS线程的操作方法有NSThread NSOperation NSOperationQueue GCD: NSThread方法有 //NSThread自动 - (IBAction)didClickNSThreadAutoButtonActi

在C#中主线程和子线程如何实现互相传递数据(转)

在C#中创建线程Thread时,可以有多种方法,而主线程和子线程之间又如何实现互相传递数据,每种创建方法传递参数的效果是不同的,逐一看一下: 一.不带参数创建Thread 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 using System;  using System.Collections.Generic;  using System.Text;  using System.Threading;  namespace

IOS中一个简单的粒子效果实现

1.效果图展示 2.实现思路 1> 首先要实现上面的效果,第一步要处理的就是一个简单的画板,在View上面用鼠标滑动的时候画出线条,这个功能可使用UIBezierPath实现 2> 关于粒子效果的实现,可以创建一个CALayer,然后用CAReplicatorLayer进行复制layer,从而达到粒子效果 3.代码实现 DrawView类的封装与编写 // // DrawView.m // 06-粒子效果 // // Created by xiaomage on 15/6/24. // Cop

网络操作不能直接写在主线程中 以及 为什么不能在子线程中更新UI控件的属性

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ //注意: 所有网络操作不能直接写在主线程中 因为所有的网络操作都是耗时的,如果加载到主线程中,会导致与用户的交互出现问题 ,所以要加载到子线程中 // [self loadImage]; [self performSelectorInBackground:@selector(loadImage) withObject:nil]; } //加

android 不能在子线程中更新ui的讨论和分析

问题描述 做过android开发基本都遇见过ViewRootImpl$CalledFromWrongThreadException,上网一查,得到结果基本都是只能在主线程中更改ui,子线程要修改ui只能post到主线程或者使用handler之类.但是仔细看看exception的描述并不是这样的,"Only the original thread that created a view hierarchy can touch its views",只有创建该 view 布局层次的原始线程

使用Handler在子线程中更新UI

Android规定只能在主线程中更新UI,如果在子线程中更新UI 的话会提示如下错误:Only the original thread that created a view hierachy can touch its view((只有原来的线程创建一个视图层次可以触摸它的视图). 只能在主线程中更新UI的原因是:android中相关的view和控件不是线程安全的,我们必须单独做处理. 有的时候需要再子线程中实现更新UI,下面介绍使用Handler实现线程通信的特点实现在子线程中更新UI. H