zoukankan      html  css  js  c++  java
  • 线程

    线程问题我会分成三篇文章来给大家做个详细的讲解

    一、线程的概念

    1.线程是进程的组成部分,一个进程可以拥有多个线程,一个线程必须有一个父线程;

    2.线程拥有自己的堆栈、自己的程序计数器和自己的局部变量,但不再拥有系统资源,它与父线程中的其他线程共享该进程所拥有的全部资源

    3.线程是独立运行的,它并不知道进程中是否还有其他线程存在,线程的执行是抢占式的,也就是说当前的运行的线程在任何时候都可能被挂起,以便另外一个线程可以运行。

    使用多线程编程的优点

    1、进程间不能共享内存,但线程之间共享内存非常容易

    2、系统创建进程需要重新为该进程分配资源,但是创建线程则代价小得多,因为它与父线程中的其他线程共享该进程所拥有的全部资源

    3、处理异步任务的主要手段,可防止UI界面假死

    线程的创建方法:

    1)创建线程并执行线程

    + (void)detachNewThreadSelector: toTarget: withObject:

     

    2)创建一个线程并返回一个线程对象但是不会执行,需要手动调用start

    - (instancetype)initWithTarget: selector: object:

     

     

    二、线程的状态

    1、当程序创建了一个线程后,该程序就处于新建状态,此时它与其他OC对象一样,仅仅由系统为其分配了内存,并初始化了其成员变量的值,此时的线程对象没有表现任何线程的动态特征,程序也不会执行线程的线程执行体

    2、当线程对象调用了start方法之后,该线程处于就绪状态,系统会为其调用方法调用栈和程序计数器,处于这种状态的线程并没有开始运行,他只是表示该线程可以运行了,至于线程何时开始运行,取决于系统的调度;倘若希望调用子线程的start方法之后子线程立即开始执行,可以在程序中加上

    [NSThread sleepForTimeInterval:0.001];   //写在哪个线程中代表哪个线程

    让当前运行的线程睡眠一毫秒,因为在这一毫秒内CPU不会空闲,他会去执行另一个处于就绪状态的线程,这就可以让子线程立即获得执行

     

    三、终止子线程

    线程会以以下三种方式之一结束,结束之后就处于死亡状态

    1、线程执行体方法执行完成,线程正常结束

    2、线程执行过程中出现了错误

    3、直接调用NSThread类的exit方法来终止当前正在执行的线程

    对象方法

    isExecuting、isFinishing判断线程当前是否处于执行状态或者执行完成状态

    如果希望在主线程中终止子线程,NSThread并没有提供方法来终止某个子线程,为了在子线程中终止子线程,可以向子线程发送一个信号(比如调用子线程的cancel方法),然后在子线程的线程执行体重进行判断,如果子线程收到过终止信号,程序应该调用NSThread类的exit方法来终止当前正在执行的循环

     

    四、线程睡眠

    如果需要让当前正在执行的线程暂停一段时间,并进入阻塞状态,则可以通过调用NSThread类的sleepXXX类方法来完成

    + (void)sleepForTimeInterval:(NSTimeInterval)ti;    //每隔多久执行一次 

    + (void)sleepUntilDate:(NSDate *)date;     //指定睡眠指导某个时间执行

     

     1 - (void)viewDidLoad {
     2     [super viewDidLoad];
     3     // NSThread 两种创建线程的方式
     4 #if 1
     5     //1.该方法创建的线程需要手动调用启动,才会去执行线程指定的方法
     6     // 线程需要一个函数作为线程的入口函数,这个函数称为线程的入口函数
     7     //  线程主要用来做并发操作,例如执行耗时的代码
     8    NSThread *tread = [[NSThread alloc] initWithTarget:self selector:@selector(doSomething) object:nil];
     9     for (int i = 0; i < 100; i++) {
    10         if (i == 20) {  
    11             //需要手动执行开始,才会调用doSomething的方法
    12             [tread start];
    13             [NSThread sleepForTimeInterval:0.001];
    14         }
    15         NSLog(@"%d",i);
    16     }
    17     //给线程取别名
    18     //tread.name = @"something";
    19 
    20 #elif 0
    21     //2.该方式创建的线程会自动执行线程的入口函数
    22     [NSThread detachNewThreadSelector:@selector(doSomething) toTarget:self withObject:nil];
    23   #endif
    24 }
    25 -(void)doSomething
    26 {
    27     // 耗时代码
    28     
    29     // 获取当前线程
    30     //NSLog(@"%@",[NSThread currentThread]);
    31     int index = 10;
    32     
    33     while (index--) {
    34         
    35         if (index == 5) {
    36             //1⃣️cancel 取消线程,并不是真正意义上的取消线程,是给线程打上取消的标志,等待取消
    37             [[NSThread currentThread] cancel];
    38         }
    39         
    40         //2⃣️.判断线程是否有取消的标志
    41         if ([[NSThread currentThread] isCancelled]) {
    42             //3⃣️.退出线程,线程销毁,系统会自动回收资源
    43             //[NSThread exit];
    44             //注意return与退出线程的区别
    45             //return;
    46         }
    47         
    48         NSLog(@"%d",index);
    49         //两种睡眠方式
    50         //1.睡眠
    51         //[NSThread sleepForTimeInterval:1];
    52         //2.指定睡眠知道某个时间执行
    53         //dateByAddingTimeInterval 追加的时间
    54 //        NSDate *curDate = [[NSDate date] dateByAddingTimeInterval:1];
    55 //        [NSThread sleepUntilDate:curDate];
    56     }
    57 }

    【注意】iOS规定只能在UI线程(即主线程)中修改UI控件的属性,因为如果程序允许任意子线程访问、修改UI控件的属性,这就需要对多个新线程的并发访问进行同步控制;否则,多个线程将会破坏UI控件内部状态的完整性

    实例:下载网络图片(如果程序在UI线程中访问网络数据,由于网络速度的不确定性,当网络传输速度比较慢时,UI线程就会被阻塞,从而导致应用失去响应,因此程序将通过网络下载图片的操作放在多线程中完成)

     1 #import "ViewController.h"
     2 
     3 @interface ViewController ()
     4 @property (weak, nonatomic) IBOutlet UIImageView *imageV;
     5 
     6 @end
     7 
     8 @implementation ViewController
     9 
    10 - (void)viewDidLoad {
    11     [super viewDidLoad];
    12     
    13 }
    14 - (IBAction)BtnAction:(id)sender {
    15     //图片地址
    16     NSString *url = @"http://image.baidu.com/search/down?tn=download&ipn=dwnl&word=download&ie=utf8&fr=result&url=http%3A%2F%2Fh.hiphotos.baidu.com%2Fzhidao%2Fwh%253D450%252C600%2Fsign%3D3dc4538262d0f703e6e79dd83dca7d0b%2F7a899e510fb30f24f570e996c895d143ac4b03b8.jpg&thumburl=http%3A%2F%2Fimg4.imgtn.bdimg.com%2Fit%2Fu%3D2019970444%2C20888940%26fm%3D21%26gp%3D0.jpg";
    17     //创建线程
    18     NSThread *downloadImage = [[NSThread alloc] initWithTarget:self selector:@selector(downLoadImage:) object:url];
    19     //启动线程
    20     [downloadImage start];
    21    
    22     
    23 }
    24 -(void)downLoadImage:(NSString *)url
    25 {
    26     NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
    27     UIImage *image = [UIImage imageWithData:data];
    28     //返回主线程刷新UI
    29     
    30     [self performSelectorOnMainThread:@selector(reloadUI:) withObject:image waitUntilDone:NO];
    31 }
    32 -(void)reloadUI:(UIImage *)image
    33 {
    34     _imageV.image = image;
    35 }
    36 @end

     

  • 相关阅读:
    【spring 事务注解配置】事务回滚
    myisam 和 innodb 对比
    mysql replace into用法详细说明
    [nginx] 配置
    【lucene】中文分词
    Lucene 4.9 document的简单应用
    Spring事务配置的五种方式
    Open-Drain与Push-Pull
    HDMI中的AVmute是什么功能
    在Keil uv5里面添加STC元器件库,不影响其他元件
  • 原文地址:https://www.cnblogs.com/Mr-Lin/p/5172299.html
Copyright © 2011-2022 走看看