进程、线程、多线程理论

       这是我对进程、线程的了解,有不足之处希望大家多多指点,我们一起学习、进步#^_^#。


一、进程:

进程是程序的一次执行,就是在操作系统中运行的程序;

进程是不能执行任务的;

进程在运行时创建的资源随着进程的终止而死亡。

 

二、线程:

1、线程是用来执行任务的,线程彻底执行完任务A才会去执行任务B

2、进程本身是不能执行任务的,进程想要执行任务必须的有线程,线程是进程内部的一个独立的执行单元,同时只能执行一个任务。线程被分为两种。主线程(用户界面线程)和子线程(工作线程或后台线程);

3、线程执行完毕就会被销毁。

4、线程有分为主线程和子线程

①主线程(又叫父线程):当应用程序启动时自动创建和启动,通常用来处理用户的输入并响应各种事件和信息。

         需要注意的是,主线程的终止也就意味着该程序的结束。

②子线程:顾名思义,子线程有主线程来创建,用来帮助主线程执行程序的后台处理任务。

         若子线程A创建子线程B,那么在创建之后子线程A和子线程B是相互独立的,多个线程之间在效果上可以同时执行。

 

一个进程中可以有多个线程,并且所有线程都在该进程的虚拟地址空间中,可以使用进程的全局变量和系统资源

 

5、线程的状态

        线程从创建、运行到结束总是处于这五种状态之一:新建状态、就绪状态、运行状态、阻塞状态、死亡状态。

①新建状态:

当用操作符new创建一个线程时,线程还没有开始运行,那么线程处于新建状态,此时程序还没有开始运行线程中的代码

就绪状态:

        一个新创建的线程并不自动开始运行,要执行线程,必须调用线程的start()方法。当线程对象调用start()方法即启动了线程,start()方法创建线程运行的系统资源,并调度线程运行run()方法。当start()方法返回后,线程就处于就绪状态。

        处于就绪状态的线程并不一定立即运行run()方法,线程还必须同其他线程竞争CPU时间,只有获得CPU时间才可以运行线程。因为在单CPU的计算机系统中,不可能同时运行多个线程,一个时刻仅有一个线程处于运行状态。因此此时可能有多个线程处于就绪状态。对多个处于就绪状态的线程是由Java运行时系统的线程调度程序(thread scheduler)来调度的。

 

    ③运行状态

        当线程获得CPU时间后,它才进入运行状态,真正开始执行run()方法。

    ④阻塞状态

        线程运行过程中,可能由于各种原因进入阻塞状态:

        1)线程通过调用sleep方法进入睡眠状态;

        2)线程调用一个在I/O上被阻塞的操作,即该操作在输入输出操作完成之前不会返回到它的调用者;

        3)线程试图得到一个锁,而该锁正被其他线程持有;

        4)线程在等待某个触发条件;

        ......           

        所谓阻塞状态是正在运行的线程没有运行结束,暂时让出CPU,这时其他处于就绪状态的线程就可以获得CPU时间,进入运行状态。

 

    ⑤ 死亡状态        有两个原因会导致线程死亡:

        1)run方法正常退出而自然死亡,

        2)一个未捕获的异常终止了run方法而使线程猝死。

        为了确定线程在当前是否存活着(就是要么是可运行的,要么是被阻塞了),需要使用isAlive方法。如果是可运行或被阻塞,这个方法返回true;如果线程仍旧是new状态且不是可运行的, 或者线程死亡了,则返回false。

 

三、多线程:

为了同时执行多个线程,就产生了多线程。

       ①目前大多数的APP都需要链接服务器,而访问服务器的速度可能快,也可能很慢。如果一个APP访问服务器的操作没有在子线程操作的话,在该APP访问服务器的过程中,该软件是不能响应用户的操作的,只有该APP访问结束以后APP才能响应用户的操作,这就造成线程阻塞,也就是我们常见的卡顿现象。一条线程在同一时间内只能执行一个任务,一个进程可以有多个线程来执行不同的任务,从而提高程序的执行效率,避免线程阻塞。

 

         ②操作系统会根据线程的优先级(线程的优先级可以手动设置)来安排CPU的时间,优先级高的线程,优先调用的几率会更大,同级的话,看线程执行的先后。

 

        ③同一时间内,CPU只能处理一条线程,只有一条线程在工作。多线程并行执行,其实就是各个线程不断切换,因为执行切换的时间很快很快,就造成了同时执行的假象,原理如下,比如A,B两个线程:

1)A执行到某一时间段要切换了,可A任务没完成,系统就会把A当前执行的位置和数据以入栈的方式保存起来

2)然后B线程执行,B执行时间到了,它的位置状态等也会被系统保存到B的栈中。

3)系统自动找到A的栈,将A之前保存的数据恢复,又可以从A之前断开的状态继续执行下去,如此循环。

 

        ④系统每开一个线程都有比较大的开销。若线程开的过多,不仅会占用大量内存和让程序变得更加复杂,而且会加重CPU的负担,这样的软件,会使你的手机在冬天变成暖手宝。

 

四、益处:

1、使用多线程可以提高程序的执行效率,避免线程阻塞造成的卡顿现象。

2、可以提高资源利用率

 

注意:一个进程中可以有多个线程,但不能滥用线程,因为:

1、开启线程需要占用一定的内存空间(默认情况下,主线程占用1M,子线程占用512KB,可以自己设置内存大小,但必须是4的倍数),如果开启大量的线程,会占用大量的内存空间,降低程序的性能

2、线程越多,CPU在调度线程上的开销就越大

3、滥用线程会使程序设计更加复杂:比如线程之间的通信、多线程的数据共享

 

 

线程例子:

 

 

//

// MoreImageViewController.m

//  多线程

//

//  Created by 王维 on 16/3/2.

//  Copyright © 2016 王维. All rights reserved.

//

 

#import "MoreImageViewController.h"

 

#define kUrl @"http://store.storeimages.cdn-apple.com/8748/as-images.apple.com/is/image/AppleInc/aos/published/images/s/38/s38ga/rdgd/s38ga-rdgd-sel-201601?wid=848&hei=848&fmt=jpeg&qlt=80&op_sharpen=0&resMode=bicub&op_usm=0.5,0.5,0,0&iccEmbed=0&layer=comp&.v=1454777389943"

 

@interface MoreImageViewController()

{

    int imageIndex;

    UIImage *image;

   NSMutableArray *threadArray;//用来存放子线程的数组

}

@end

 

@implementation MoreImageViewController

 

- (void)viewDidLoad {

    [super viewDidLoad];

    

    self.view.backgroundColor = [UIColor blueColor];

    self.edgesForExtendedLayout = UIRectEdgeNone;

    

    imageIndex = 100;

    

    threadArray = [NSMutableArray array];

    

//    1、创建多个UIImageView

    for (int row = 0; row < 3;row++) {

       for (intlist = 0; list < 2;list++) {

           UIImageView *imageView= [[UIImageView alloc]initWithFrame:CGRectMake(10+list*200, 10+row*200, 200, 200)];

           imageView.backgroundColor= [UIColor greenColor];

           imageView.tag = imageIndex++;

           [self.view addSubview:imageView];

       }

    }

//   2 创建多个子线程

    for (int index= 0; index < 6;index++) {

       

//        object:@(index)object传的参数是index是为了区别子线程

        NSThread *thread = [[NSThread alloc]initWithTarget:selfselector:@selector(thread:)object:@(index)];

       [thread start];

       

       [threadArray addObject:thread];

    }

    

}

 

//int类型的数据用@()包起来就转换成nsnumber类型。创建线程中的withObject:@(index)表明需要一个NSNumber类型来接受

//通过URL加载图片

- (void)thread:(NSNumber*)sender{

    

//    3、加载图片

    image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:kUrl]]];

    

//    通过线程休眠实现顺序加载

    [NSThread sleepForTimeInterval:[sender intValue]];

    

    

//    在这里加上一个判断,获取当前线程的状态,如果是休眠状态,就让它退出

    NSThread *thread = [NSThreadcurrentThread];

    if (thread.isCancelled== YES) {

       [NSThread exit];

    }

    

//    4、回到主线程

    [self performSelectorOnMainThread:@selector(updateUI:) withObject:sender waitUntilDone:YES];

    

 

}

 

//5、更新UI

- (void)updateUI:(NSNumber*)sender{

    

//    ①先找到某个线程对应的imageView

    UIImageView *imageView = [self.view viewWithTag:[senderintValue]+100];

   imageView.image = image;

    

}

 

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    

    [NSThread currentThread];

    

    NSLog(@"%@",threadArray);

    

    for (int index= 0; index < 6;index++) {

       NSThread *thread = threadArray[index];

       if (thread.isFinished== NO) {

//            点击屏幕,取消未完成的线程

           [thread cancel];

       }

    }

 

}

@end

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值