分享

多线程

 叹落花 2014-12-20

进程是系统资源管理的最小单位。线程是程序执行的最小单位。多线程是一个进程里包含多个线程。一个进程数据会加载到一个内存区间中,其中的线程共享相同的内存空间。各个进程的地址是独立的,只有进程能刷新UI、更新数据。线程需要手动开启。

建立一个简单售票系统,连接线程的运行。首先创建一个单视图工程,在.h文件中代码:

  1. @interface LinViewController : UIViewController  
  2. {  
  3.     //声明剩余票数、卖出票数成员名  
  4.     int _leftTickets;  
  5.     int _soldTickets;  
  6.     //声明线程成员名  
  7.     NSThread * _firstThread;  
  8.     NSThread * _secondThread;  
  9.     NSThread * _thridThread;  
  10.     //声明线程锁  
  11.     NSCondition * _ticketsCondition;  
  12. }  
  13. //创建标签栏的对象,用来显示剩余票数、卖出票数、当前线程名  
  14. @property (retain, nonatomic) UILabel * leftLabel;  
  15. @property (retain, nonatomic) UILabel * soldLabel;  
  16. @property (retain, nonatomic) UILabel * currentThreadLabel;  
  17.   
  18. @end  
在.m文件中的代码:
  1. #import "LinViewController.h"  
  2.   
  3. //预编译变量,设置票的总数量  
  4. #define MaxTickets 100  
  5.   
  6. @implementation LinViewController  
  7.   
  8. //释放创建的对象  
  9. - (void)dealloc  
  10. {  
  11.     [_leftLabel release];  
  12.     [_soldLabel release];  
  13.     [_currentThreadLabel release];  
  14.     [super dealloc];  
  15. }  
  16.   
  17. - (void)viewDidLoad  
  18. {  
  19.     [super viewDidLoad];  
  20.   
  21.     //加载辅助的标签栏,只显示内容  
  22.     [self addLabel:nil];  
  23.       
  24.     //设置标签栏对象的位置  
  25.     self.leftLabel = [[UILabel alloc]initWithFrame:CGRectMake(150, 90, 100, 30)];  
  26.     self.soldLabel = [[UILabel alloc]initWithFrame:CGRectMake(150, 170, 100, 30)];  
  27.     self.currentThreadLabel = [[UILabel alloc]initWithFrame:CGRectMake(150, 250, 100, 30)];  
  28.     //设置标签栏对象的背景颜色  
  29.     self.leftLabel.backgroundColor = [UIColor lightGrayColor];  
  30.     self.soldLabel.backgroundColor = [UIColor lightGrayColor];  
  31.     self.currentThreadLabel.backgroundColor = [UIColor lightGrayColor];  
  32.     //把标签栏添加到当前的视图中  
  33.     [self.view addSubview:self.leftLabel];  
  34.     [self.view addSubview:self.soldLabel];  
  35.     [self.view addSubview:self.currentThreadLabel];  
  36.       
  37.     //初始化成员并赋值  
  38.     _leftTickets = MaxTickets;  
  39.     _soldTickets = 0;  
  40.     _ticketsCondition = [[NSCondition alloc]init];  
  41.       
  42.     //创建按钮对象  
  43.     UIButton * pButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];  
  44.     //设置按钮的位置  
  45.     [pButton setFrame:CGRectMake(80, 340, 180, 40)];  
  46.     //为按钮添加标题  
  47.     [pButton setTitle:@"开始卖票" forState:UIControlStateNormal];  
  48.     //设置按钮的方法,响应方式  
  49.     [pButton addTarget:self action:@selector(threadStart:) forControlEvents:UIControlEventTouchUpInside];  
  50.     //把按钮添加到当前视图中  
  51.     [self.view addSubview:pButton];  
  52. }  
  53. #pragma mark-------增加辅助标签栏  
  54. - (void)addLabel:(id)sender  
  55. {  
  56.     //初始化标签栏对象对设置位置  
  57.     UILabel * pLabel = [[UILabel alloc]initWithFrame:CGRectMake(10, 20, 300, 40)];  
  58.     UILabel * pLabel1 = [[UILabel alloc]initWithFrame:CGRectMake(10, 80, 120, 50)];  
  59.     UILabel * pLabel2 = [[UILabel alloc]initWithFrame:CGRectMake(10, 160, 120, 50)];  
  60.     UILabel * pLabel3 = [[UILabel alloc]initWithFrame:CGRectMake(10, 240, 120, 50)];  
  61.     //设置标签栏的内容文本  
  62.     pLabel.text = @"模拟火车票销售---多线程";  
  63.     pLabel1.text = @"剩余票数";  
  64.     pLabel2.text = @"售出票数";  
  65.     pLabel3.text = @"当前进程";  
  66.     //设置标签栏的背景颜色  
  67.     pLabel.backgroundColor = [UIColor clearColor];  
  68.     pLabel1.backgroundColor = [UIColor clearColor];  
  69.     pLabel2.backgroundColor = [UIColor clearColor];  
  70.     pLabel3.backgroundColor = [UIColor clearColor];  
  71.     //设置标签栏的文本居中  
  72.     pLabel.textAlignment = NSTextAlignmentCenter;  
  73.     pLabel1.textAlignment = NSTextAlignmentCenter;  
  74.     pLabel2.textAlignment = NSTextAlignmentCenter;  
  75.     pLabel3.textAlignment = NSTextAlignmentCenter;  
  76.     //把标签栏对象添加到视图中  
  77.     [self.view addSubview:pLabel];  
  78.     [self.view addSubview:pLabel1];  
  79.     [self.view addSubview:pLabel2];  
  80.     [self.view addSubview:pLabel3];  
  81.     //释放创建的对象  
  82.     [pLabel release];  
  83.     [pLabel1 release];  
  84.     [pLabel2 release];  
  85.     [pLabel3 release];  
  86. }  
  87. #pragma mark-------开始卖票,线程开始运行  
  88. - (void)threadStart:(id)sender  
  89. {  
  90.     //初始化子线程,设置子线程的方法  
  91.     _firstThread = [[NSThread alloc]initWithTarget:self selector:@selector(sellTickets:) object:nil];  
  92.     //设置子线程的名字  
  93.     [_firstThread setName:@"thread-1"];  
  94.     //??手动开启子线程,必须添加,系统不能自主进行  
  95.     [_firstThread start];  
  96.       
  97.     _secondThread = [[NSThread alloc]initWithTarget:self selector:@selector(sellTickets:) object:nil];  
  98.     [_secondThread setName:@"thread-2"];  
  99.     [_secondThread start];  
  100.       
  101.     _thridThread = [[NSThread alloc]initWithTarget:self selector:@selector(sellTickets:) object:nil];  
  102.     [_thridThread setName:@"thread-3"];  
  103.     [_thridThread start];  
  104. }  
  105. //卖票的方法  
  106. - (void)sellTickets:(id)sender  
  107. {  
  108.     while (YES)  
  109.     {  
  110.         //??锁定线程,防止同一子线程多次运行,必须有  
  111.         [_ticketsCondition lock];  
  112.         //判断票是否卖完  
  113.         if (_leftTickets > 0)  
  114.         {  
  115.             //设置线程停止0.1秒  
  116.             [NSThread sleepForTimeInterval:0.1];  
  117.             //卖票的算法  
  118.             _leftTickets--;  
  119.             _soldTickets = MaxTickets - _leftTickets;  
  120.         }  
  121.         else if (_leftTickets == 0)  
  122.         {  
  123.             NSLog(@"票已经卖完!");  
  124.             break;  
  125.         }  
  126.         //子线程调用主线程更新视图,只有进程能更新视图  
  127.         [self performSelectorOnMainThread:@selector(updateMyView:) withObject:[[NSThread currentThread]name] waitUntilDone:YES];  
  128.         //输出剩余票数、售出票数、当前线程,可以省略  
  129.         NSLog(@"剩余票数:%i售出票数:%i当前线程%@",_leftTickets,_soldTickets,[[NSThread currentThread]name]);  
  130.         //线程解锁  
  131.         [_ticketsCondition unlock];  
  132.     }  
  133. }  
  134. #pragma mark-------更新界面,进程可以,线程不可以  
  135. - (void)updateMyView:(id)sender  
  136. {  
  137.     //设置标签栏的显示内容  
  138.     self.leftLabel.text = [NSString stringWithFormat:@"%i",_leftTickets];  
  139.     self.soldLabel.text = [NSString stringWithFormat:@"%i",_soldTickets];  
  140.     self.currentThreadLabel.text = (NSString *)sender;  
  141.     //判断是否卖完,若卖完则弹出警告框  
  142.     if (_leftTickets == 0)  
  143.     {  
  144.         UIAlertView * pAlertView = [[UIAlertView alloc]initWithTitle:@"温馨提示" message:@"票已经全部售出!" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil nil];  
  145.         [pAlertView show];  
  146.         [pAlertView release];  
  147.     }      
  148. }  
  149.   
  150. - (void)didReceiveMemoryWarning  
  151. {  
  152.     [super didReceiveMemoryWarning];  
  153. }  
  154.   
  155. @end  




    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多