今天我们学习的主要是线程与进程,
本章要点
线程与进程
NSThread
NSOperation
GCD
1、进程:
是活动的程序,是一个容器
是系统资源管理的最小单位
切换代价较高
2、线程:
- 是在进程容器中运行,实际工作的代码
是程序执行的最小单位
切换代价低
3、单线程:
一个进程内只有一个线程
一个进程的数据通常加载在同一内存中!
4、多线程:
一个进程内有多个线程
多个线程通常共享同一内存中的数据!
线程与进程切换的区别:
线程完全共享相同的地址空间,切换代价低
进程的地址空间是独立的,切换代价高
5、进程与线程之间的区别:
简而言之,一个程序至少有一个进程,一个进程至少有一个线程.
线程的划分尺度小于进程,使得多线程程序的并发性高。
另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
6、线程的好处 (1)易于调度。
(2)提高并发性。通过线程可方便有效地实现并发性。进程可创建多个线程来执行同一程序的不同部分。
(3)开销少。创建线程比创建进程要快,所需开销很少。。
(4)利于充分发挥多处理器的功能。通过创建多线程进程(即一个进程可具有两个或更多个线程),每个线程在一个处理器上运行,从而实现应用程序的并发性,使每个处理器都得到充分运行。
7、NSThread:
手动调用start方法开启:
(id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument;
直接生成一个线程并启动
+(void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument;
创建一个NSThread工程
(void)viewDidLoad
{
[super viewDidLoad];
//这个方法可以直接生成一个线程并启动它,而且无需为线程的清理负责。
[NSThread detachNewThreadSelector: @selector(downloadImage:) toTarget:self withObject:kURL];
}
#define kURL @“http://img.article.pchome.net/new/w600/00/31/34/44/pic_lib/wn/347337.jpg”
(void)downloadImage:(NSString *)url
{
NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]];
UIImage *image = [[UIImage alloc] initWithData:data];
if (image == nil)
{
}
else
{
[self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];
}
}
8、NSOperation:
创建方法:
- (void)initWithTarget:(id)target selector:(SEL)sel object:(id)arg;
创建一个NSOperation工程
#define kURL @“http://img.article.pchome.net/new/w600/00/31/34/44/pic_lib/wm/3457337.jpg”
(void)viewDidLoad
{
[super viewDidLoad];
NSInvocationOperation * operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downloadImage:)object:kURL];
NSOperationQueue * queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation];
}
(void)downloadImage:(NSString *)url
{
NSData * data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
UIImage * image = [UIImage imageWithData;data];
[self performSelectorOnMainThread: @selector(updateUI withObject:image waitUntilDone:YES)];
}
(void)updateUI:(UIImage *)image
{
self.imageVIew.image = image;
}
创建方法:
- (id)initWithTarget:(id)target selector:(SEL)sel object:(id)arg;
创建一个NSOperation工程
#define kURL @“http://img.article.pchome.net/new/w600/00/31/34/44/pic_lib/wm/3457337.jpg”
(void)viewDidLoad
{
[super viewDidLoad];
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadImage:)object:kURL];
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[queue addOperation:operation];
}
(void)downloadImage:(NSString *)url
{
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
UIImage *image = [UIImage imageWithData:data];
[self performSelectorOnMainThread: @selector(updateUI withObject:image waitUntilDone:YES)];
}
9、相关代码示例:
在AppDelegate.h文件中
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
在AppDelegate.m文件中
#import "AppDelegate.h"
#import "BoThreadViewController.h"
#import "BoThreadTwoViewController.h"
@implementation AppDelegate
- (void)dealloc
{
[_window release];
[super dealloc];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
self.window.backgroundColor = [UIColor whiteColor];
//创建第一个标签视图控制器
BoThreadViewController *pThreadVC = [[BoThreadViewController alloc]initWithNibName:nil bundle:nil];
//创建第二个标签视图控制器
BoThreadTwoViewController *pThreadTwoVC = [[BoThreadTwoViewController alloc]initWithNibName:nil bundle:nil];
UITabBarController *pTabbarVC = [[UITabBarController alloc]init];
//将视图控制器加入到标签栏中
pTabbarVC.viewControllers = [NSArray arrayWithObjects:pThreadVC,pThreadTwoVC, nil];
self.window.rootViewController = pTabbarVC;
[pThreadTwoVC release];
[pThreadVC release];
[pTabbarVC release];
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
}
- (void)applicationWillTerminate:(UIApplication *)application
{
}
@end
在BoThreadViewController.h文件中(相关按钮都是以拖拽形式进行)
#import <UIKit/UIKit.h>
@interface BoThreadViewController : UIViewController
@property (retain, nonatomic) IBOutlet UILabel *labelResult;
@property (retain, nonatomic) IBOutlet UIProgressView *myProgressView;
@property (retain, nonatomic) IBOutlet UIButton *btnStart;
- (IBAction)btnPressed:(id)sender;
@end
在BoThreadViewController.m文件中
#import "BoThreadViewController.h"
@interface BoThreadViewController ()
@end
@implementation BoThreadViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.tabBarItem.title = @"Thread_1";
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
//设置当前进度条的进度
self.myProgressView.progress = 0;
//设置文本
self.labelResult.text = [NSString stringWithFormat:@"%.2f",self.myProgressView.progress];
}
- (IBAction)btnPressed:(id)sender
{
//设置按钮的状态为隐藏状态
self.btnStart.hidden = YES;
//创建一个自动执行的线程出来
[NSThread detachNewThreadSelector:@selector(startTheBackGroundJob:) toTarget:self withObject:nil];
}
//子线程开启的方法
- (void)startTheBackGroundJob:(id)sender
{
[self performSelectorOnMainThread:@selector(updateProgressView:) withObject:nil waitUntilDone:NO];
}
//完成界面的更新
- (void)updateProgressView:(id)sender
{
//让进度条完成增加
self.myProgressView.progress += 0.1;
//临时变量获取进度条的值
float value = self.myProgressView.progress;
//根据该值进行判断是否(进行重复调用,递归压栈的操作形式)
if (value < 1)
{
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(updateProgressView:) userInfo:nil repeats:YES];
}
else
{
self.btnStart.hidden = NO;
}
//更新界面进度条的显示结果
self.labelResult.text = [NSString stringWithFormat:@"%.2f",value];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (void)dealloc {
[_labelResult release];
[_myProgressView release];
[_btnStart release];
[super dealloc];
}
@end
在BoThreadTwoViewController.h文件中(相关按钮都是以拖拽形式进行)
#import <UIKit/UIKit.h>
@interface BoThreadTwoViewController : UIViewController
{
int _saleTickets;
int _leftTickets;
NSThread *_firstThread;
NSThread *_secondThread;
NSCondition *_ticketsCondition;
}
@property (retain, nonatomic) IBOutlet UILabel *labelLeftTickes;
@property (retain, nonatomic) IBOutlet UILabel *labelSaleTickes;
@property (retain, nonatomic) IBOutlet UILabel *labelCurrentThread;
@end
在BoThreadTwoViewController.m文件中
#import "BoThreadTwoViewController.h"
@interface BoThreadTwoViewController ()
@end
@implementation BoThreadTwoViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.tabBarItem.title = @"ThreadTwo";
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_leftTickets = 100;
_saleTickets = 0;
_ticketsCondition = [[NSCondition alloc]init];
//添加一个Button
UIButton *pBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[pBtn setFrame:CGRectMake(30, 340, 260, 40)];
[pBtn setTitle:@"Start" forState:UIControlStateNormal];
[pBtn addTarget:self action:@selector(threadStart:) forControlEvents:UIControlEventTouchUpInside];
//将按钮添加到视图
[self.view addSubview:pBtn];
}
//按钮关联的方法
- (void)threadStart:(id)sender
{
_firstThread = [[NSThread alloc]initWithTarget:self selector:@selector(run:) object:nil];
[_firstThread setName:@"Thread_One"];
[_firstThread start];
_secondThread = [[NSThread alloc]initWithTarget:self selector:@selector(run:) object:nil];
[_secondThread setName:@"Thread_Two"];
[_secondThread start];
}
//子线程进行的逻辑操作
- (void)run:(id)sender
{
//恒为真
while (TRUE)
{
//线程锁保护,防止线程数据混乱
[_ticketsCondition lock];
if (_leftTickets > 0)
{
[NSThread sleepForTimeInterval:0.1];
_saleTickets++;
_leftTickets = 100 - _saleTickets;
NSString *pCurrentThreadName = [[NSThread currentThread]name];
NSLog(@"售出票数为u:%i,剩余票数为:%i,当前线程为:%@",_saleTickets,_leftTickets,pCurrentThreadName);
}
else if (_leftTickets == 0)
{
NSLog(@"票已售完!");
break;
}
[self performSelectorOnMainThread:@selector(updateMyView:) withObject:[[NSThread currentThread]name] waitUntilDone:YES];
[_ticketsCondition unlock];
}
}
//更新界面的方法
- (void)updateMyView:(id)sender
{
self.labelLeftTickes.text = [NSString stringWithFormat:@"%i",_leftTickets];
self.labelSaleTickes.text = [NSString stringWithFormat:@"%i",_saleTickets];
self.labelCurrentThread.text = (NSString *)sender;
if (_leftTickets == 0)
{
UIAlertView *pAlertView = [[UIAlertView alloc]initWithTitle:@"通知" message:@"今日票已售完" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"确认", nil];
[pAlertView show];
[pAlertView release];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (void)dealloc
{
[_ticketsCondition release];
[_labelLeftTickes release];
[_labelSaleTickes release];
[_labelCurrentThread release];
[super dealloc];
}
@end