《电子技术应用》
您所在的位置:首页 > 模拟设计 > 设计应用 > 利用iphone的多线程实现“售票系统”
利用iphone的多线程实现“售票系统”
摘要: 在这篇文章中,笔者就拿大多数Java教程中经典的“售票系统多线程”作为实际例子,在iphone中进行同样的实现。
Abstract:
Key words :

  Java因为其本身支持多线程而给程序员带来很多方便,其实在iphone开发中也支持多线程编程,并且一点也不比java麻烦。

  在这篇文章中,笔者就拿大多数Java教程中经典的“售票系统多线程”作为实际例子,在iphone中进行同样的实现。

  下面是java版本的“售票系统多线程”代码:

  package demo;

  public class SellTickets implements Runnable{

  private int tickets=100;

  public void run() {

  int count=0;

  while (true)

  {

  //上锁

  synchronized(this){

  if (tickets》0){

  try {

  Thread.sleep(500);

  } catch (InterruptedException e) {

  e.printStackTrace();

  }

  count=100-tickets;

  System.out.println(“当前票数是:”+tickets+“售出”+count

  +“线程名:”+Thread.currentThread().getName());

  tickets--;

  }else{

  break;

  }

  }

  }

  }

  public static void main(String[] args) {

  SellTickets r=new SellTickets();

  Thread t1=new Thread(r,“t1”);

  t1.start();

  Thread t2=new Thread(r,“t2”);

  t2.start();

  Thread t3=new Thread(r,“t3”);

  t3.start();

  Thread t4=new Thread(r,“t4”);

  t4.start();

  }

  }

  以上java版本的代码执行后控制台输出如下:

  当前票数是:100售出0线程名:t1

  当前票数是:99售出1线程名:t2

  当前票数是:98售出2线程名:t3

  当前票数是:97售出3线程名:t4

  当前票数是:96售出4线程名:t1

  当前票数是:95售出5线程名:t2

  当前票数是:94售出6线程名:t3

  当前票数是:93售出7线程名:t4

  当前票数是:92售出8线程名:t1

  当前票数是:91售出9线程名:t2

  当前票数是:90售出10线程名:t3

  当前票数是:89售出11线程名:t4

  当前票数是:88售出12线程名:t1

  当前票数是:87售出13线程名:t2

  当前票数是:86售出14线程名:t3

  当前票数是:85售出15线程名:t4

  当前票数是:84售出16线程名:t1

  当前票数是:83售出17线程名:t2

  当前票数是:82售出18线程名:t3

  当前票数是:81售出19线程名:t4

  当前票数是:80售出20线程名:t1

  当前票数是:79售出21线程名:t2

  当前票数是:78售出22线程名:t3

  当前票数是:77售出23线程名:t4

  当前票数是:76售出24线程名:t1

  当前票数是:75售出25线程名:t2

  当前票数是:74售出26线程名:t3

  当前票数是:73售出27线程名:t4

  ……

  可以在iphone中进行同样的实现,Iphone的Frameworks/Foundation.framework框架支持多线程编程,接口定义在:

  /Xcode3.1.4/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.1.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSThread.h

  到相应的目录下打开此文件,可以看到绝大多数java中的接口这里也都能找到相应的实现,如下:

  /* NSThread.h

  Copyright (c) 1994-2007, Apple Inc. All rights reserved.

  */

  #import 《Foundation/NSObject.h》

  #import 《Foundation/NSDate.h》

  @class NSArray, NSMutableDictionary, NSDate;

  @interface NSThread : NSObject {

  @private

  id _private;

  uint8_t _bytes[44];

  }

  + (NSThread *)currentThread;

  + (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument;

  + (BOOL)isMultiThreaded;

  - (NSMutableDictionary *)threadDictionary;

  + (void)sleepUntilDate:(NSDate *)date;

  + (void)sleepForTimeInterval:(NSTimeInterval)ti;

  + (void)exit;

  #if MAC_OS_X_VERSION_10_2 《= MAC_OS_X_VERSION_MAX_ALLOWED

  + (double)threadPriority;

  + (BOOL)setThreadPriority:(double)p;

  #endif

  #if MAC_OS_X_VERSION_10_5 《= MAC_OS_X_VERSION_MAX_ALLOWED

  + (NSArray *)callStackReturnAddresses;

  - (void)setName:(NSString *)n;

  - (NSString *)name;

  - (NSUInteger)stackSize;

  - (void)setStackSize:(NSUInteger)s;

  - (BOOL)isMainThread;

  + (BOOL)isMainThread; // reports whether current thread is main

  + (NSThread *)mainThread;

  - (id)init; // designated initializer

  - (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument;

  - (BOOL)isExecuting;

  - (BOOL)isFinished;

  - (BOOL)isCancelled;

  - (void)cancel;

  - (void)start;

  - (void)main; // thread body method

  #endif

  @end

  FOUNDATION_EXPORT NSString * const NSWillBecomeMultiThreadedNotification;

  FOUNDATION_EXPORT NSString * const NSDidBecomeSingleThreadedNotification;

  FOUNDATION_EXPORT NSString * const NSThreadWillExitNotification;

  @interface NSObject (NSThreadPerformAdditions)

  #if MAC_OS_X_VERSION_10_2 《= MAC_OS_X_VERSION_MAX_ALLOWED

  - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array;

  - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;

  // equivalent to the first method with kCFRunLoopCommonModes

  #endif

  #if MAC_OS_X_VERSION_10_5 《= MAC_OS_X_VERSION_MAX_ALLOWED

  - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array;

  - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;

  // equivalent to the first method with kCFRunLoopCommonModes

  - (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg;

  #endif

  @end

  Java因为其本身支持多线程而给程序员带来很多方便,其实在iphone的开发中也支持多线程编程,并且一点也不比java麻烦。

  在这篇文章中,笔者就拿大多数Java教程中经典的“售票系统多线程”作为实际例子,在iphone中进行同样的实现。

  下面是java版本的“售票系统多线程”代码:

  package demo;

  public class SellTickets implements Runnable{

  private int tickets=100;

  public void run() {

  int count=0;

  while (true)

  {

  //上锁

  synchronized(this){

  if (tickets》0){

  try {

  Thread.sleep(500);

  } catch (InterruptedException e) {

  e.printStackTrace();

  }

  count=100-tickets;

  System.out.println(“当前票数是:”+tickets+“售出”+count

  +“线程名:”+Thread.currentThread().getName());

  tickets--;

  }else{

  break;

  }

  }

  }

  }

  public static void main(String[] args) {

  SellTickets r=new SellTickets();

  Thread t1=new Thread(r,“t1”);

  t1.start();

  Thread t2=new Thread(r,“t2”);

  t2.start();

  Thread t3=new Thread(r,“t3”);

  t3.start();

  Thread t4=new Thread(r,“t4”);

  t4.start();

  }

  }

  以上java版本的代码执行后控制台输出如下:

  当前票数是:100售出0线程名:t1

  当前票数是:99售出1线程名:t2

  当前票数是:98售出2线程名:t3

  当前票数是:97售出3线程名:t4

  当前票数是:96售出4线程名:t1

  当前票数是:95售出5线程名:t2

  当前票数是:94售出6线程名:t3

  当前票数是:93售出7线程名:t4

  当前票数是:92售出8线程名:t1

  当前票数是:91售出9线程名:t2

  当前票数是:90售出10线程名:t3

  当前票数是:89售出11线程名:t4

  当前票数是:88售出12线程名:t1

  当前票数是:87售出13线程名:t2

  当前票数是:86售出14线程名:t3

  当前票数是:85售出15线程名:t4

  当前票数是:84售出16线程名:t1

  当前票数是:83售出17线程名:t2

  当前票数是:82售出18线程名:t3

  当前票数是:81售出19线程名:t4

  当前票数是:80售出20线程名:t1

  当前票数是:79售出21线程名:t2

  当前票数是:78售出22线程名:t3

  当前票数是:77售出23线程名:t4

  当前票数是:76售出24线程名:t1

  当前票数是:75售出25线程名:t2

  当前票数是:74售出26线程名:t3

  当前票数是:73售出27线程名:t4

  ……

  可以在iphone中进行同样的实现,Iphone的Frameworks/Foundation.framework框架支持多线程编程,接口定义在:

  /Xcode3.1.4/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.1.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSThread.h

  到相应的目录下打开此文件,可以看到绝大多数java中的接口这里也都能找到相应的实现,如下:

  /* NSThread.h

  Copyright (c) 1994-2007, Apple Inc. All rights reserved.

  */

  #import 《Foundation/NSObject.h》

  #import 《Foundation/NSDate.h》

  @class NSArray, NSMutableDictionary, NSDate;

  @interface NSThread : NSObject {

  @private

  id _private;

  uint8_t _bytes[44];

  }

  + (NSThread *)currentThread;

  + (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument;

  + (BOOL)isMultiThreaded;

  - (NSMutableDictionary *)threadDictionary;

  + (void)sleepUntilDate:(NSDate *)date;

  + (void)sleepForTimeInterval:(NSTimeInterval)ti;

  + (void)exit;

  #if MAC_OS_X_VERSION_10_2 《= MAC_OS_X_VERSION_MAX_ALLOWED

  + (double)threadPriority;

  + (BOOL)setThreadPriority:(double)p;

  #endif

  #if MAC_OS_X_VERSION_10_5 《= MAC_OS_X_VERSION_MAX_ALLOWED

  + (NSArray *)callStackReturnAddresses;

  - (void)setName:(NSString *)n;

  - (NSString *)name;

  - (NSUInteger)stackSize;

  - (void)setStackSize:(NSUInteger)s;

  - (BOOL)isMainThread;

  + (BOOL)isMainThread; // reports whether current thread is main

  + (NSThread *)mainThread;

  - (id)init; // designated initializer

  - (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument;

  - (BOOL)isExecuting;

  - (BOOL)isFinished;

  - (BOOL)isCancelled;

  - (void)cancel;

  - (void)start;

  - (void)main; // thread body method

  #endif

  @end

  FOUNDATION_EXPORT NSString * const NSWillBecomeMultiThreadedNotification;

  FOUNDATION_EXPORT NSString * const NSDidBecomeSingleThreadedNotification;

  FOUNDATION_EXPORT NSString * const NSThreadWillExitNotification;

  @interface NSObject (NSThreadPerformAdditions)

  #if MAC_OS_X_VERSION_10_2 《= MAC_OS_X_VERSION_MAX_ALLOWED

  - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array;

  - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;

  // equivalent to the first method with kCFRunLoopCommonModes

  #endif

  #if MAC_OS_X_VERSION_10_5 《= MAC_OS_X_VERSION_MAX_ALLOWED

  - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array;

  - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;

  // equivalent to the first method with kCFRunLoopCommonModes

  - (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg;

  #endif

  @end

  从接口的定义中可以知道,NSThread和大多数iphone的接口对象一样,有两种方式可以初始化:

  一种使用initWithTarget :(id)target selector:(SEL)selector object:(id)argument,但需要负责在对象的retain count为0时调用对象的release方法清理对象。

  另一种则使用所谓的convenient method,这个方便接口就是detachNewThreadSelector,这个方法可以直接生成一个线程并启动它,而且无需为线程的清理负责。

  因为在笔者的iphone版本“售票系统多线程”程序中需要设置线程的诸多参数,所以需要采用第一种方法来生成线程对象并自己启动它们。

  首先,新建一个“Window-based Application”项目,并命名为SellTickets,接下来在SellTicketsAppDelegate.h文件中声明以下变量:

  //

  // SellTicketsAppDelegate.h

  // SellTickets

  //

  // Created by sun dfsun2009 on 09-11-10.

  // Copyright __MyCompanyName__ 2009. All rights reserved.

  //

  #import 《UIKit/UIKit.h》

  @interface SellTicketsAppDelegate : NSObject 《UIApplicationDelegate》 {

  int tickets;

  int count;

  NSThread* ticketsThreadone;

  NSThread* ticketsThreadtwo;

  UIWindow *window;

  }

  @property (nonatomic, retain) IBOutlet UIWindow *window;

  @end

  笔者在头文件中声明了两个NSThread的指针,下面需要在*.m文件中初始化并实现它们,如下:

  //

  // SellTicketsAppDelegate.m

  // SellTickets

  //

  // Created by sun dfsun2009 on 09-11-10.

  // Copyright __MyCompanyName__ 2009. All rights reserved.

  //

  #import “SellTicketsAppDelegate.h”

  @implementation SellTicketsAppDelegate

  @synthesize window;

  - (void)applicationDidFinishLaunching:(UIApplication *)application {

  tickets = 100;

  count = 0;

  ticketsThreadone = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];

  [ticketsThreadone setName:@“Thread-1”];

  [ticketsThreadone start];

  ticketsThreadtwo = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];

  [ticketsThreadtwo setName:@“Thread-2”];

  [ticketsThreadtwo start];

  //[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];

  // Override point for customization after application launch

  [window makeKeyAndVisible];

  }

  - (void)run{

  while (TRUE) {

  if(tickets 》 0)

  {

  [NSThread sleepForTimeInterval:0.5];

  count = 100 - tickets;

  NSLog(@“当前票数是:%d,售出:%d,线程名:%@”,tickets,count,[[NSThread currentThread] name]);

  tickets--;

  }else

  {

  break;

  }

  }

  }

  - (void)dealloc {

  [ticketsThreadone release];

  [ticketsThreadtwo release];

  [window release];

  [super dealloc];

  }

  @end

  笔者在实现中用alloc初始化了两个NSThread对象并分别把它们命名为“Thread-1”和“Thread-2”,运行程序可以看到如下输出:

  [Session started at 2009-11-10 14:25:26 +0800.]

  2009-11-10 14:25:28.814 SellTickets[1298:4103] 当前票数是:100,售出:0,线程名:Thread-1

  2009-11-10 14:25:28.814 SellTickets[1298:4203] 当前票数是:100,售出:0,线程名:Thread-2

  2009-11-10 14:25:29.316 SellTickets[1298:4103] 当前票数是:98,售出:2,线程名:Thread-1

  2009-11-10 14:25:29.316 SellTickets[1298:4203] 当前票数是:98,售出:2,线程名:Thread-2

  2009-11-10 14:25:29.817 SellTickets[1298:4103] 当前票数是:96,售出:4,线程名:Thread-1

  2009-11-10 14:25:29.817 SellTickets[1298:4203] 当前票数是:96,售出:4,线程名:Thread-2

  2009-11-10 14:25:30.318 SellTickets[1298:4103] 当前票数是:94,售出:6,线程名:Thread-1

  2009-11-10 14:25:30.318 SellTickets[1298:4203] 当前票数是:94,售出:6,线程名:Thread-2

  2009-11-10 14:25:30.819 SellTickets[1298:4103] 当前票数是:92,售出:8,线程名:Thread-1

  2009-11-10 14:25:30.819 SellTickets[1298:4203] 当前票数是:92,售出:8,线程名:Thread-2

  2009-11-10 14:25:31.320 SellTickets[1298:4103] 当前票数是:90,售出:10,线程名:Thread-1

  2009-11-10 14:25:31.320 SellTickets[1298:4203] 当前票数是:90,售出:10,线程名:Thread-2

  2009-11-10 14:25:31.820 SellTickets[1298:4103] 当前票数是:88,售出:12,线程名:Thread-1

  2009-11-10 14:25:31.821 SellTickets[1298:4203] 当前票数是:87,售出:13,线程名:Thread-2

  2009-11-10 14:25:32.321 SellTickets[1298:4103] 当前票数是:86,售出:14,线程名:Thread-1

  2009-11-10 14:25:32.322 SellTickets[1298:4203] 当前票数是:86,售出:14,线程名:Thread-2

  2009-11-10 14:25:32.823 SellTickets[1298:4103] 当前票数是:84,售出:16,线程名:Thread-1

  2009-11-10 14:25:32.823 SellTickets[1298:4203] 当前票数是:83,售出:17,线程名:Thread-2

  2009-11-10 14:25:33.323 SellTickets[1298:4103] 当前票数是:82,售出:18,线程名:Thread-1

  2009-11-10 14:25:33.324 SellTickets[1298:4203] 当前票数是:81,售出:19,线程名:Thread-2

  2009-11-10 14:25:33.824 SellTickets[1298:4103] 当前票数是:80,售出:20,线程名:Thread-1

  2009-11-10 14:25:33.825 SellTickets[1298:4203] 当前票数是:79,售出:21,线程名:Thread-2

  2009-11-10 14:25:34.325 SellTickets[1298:4103] 当前票数是:78,售出:22,线程名:Thread-1

  2009-11-10 14:25:34.326 SellTickets[1298:4203] 当前票数是:77,售出:23,线程名:Thread-2

  2009-11-10 14:25:34.826 SellTickets[1298:4103] 当前票数是:76,售出:24,线程名:Thread-1

  2009-11-10 14:25:34.827 SellTickets[1298:4203] 当前票数是:75,售出:25,线程名:Thread-2

  2009-11-10 14:25:35.327 SellTickets[1298:4103] 当前票数是:74,售出:26,线程名:Thread-1

  2009-11-10 14:25:35.328 SellTickets[1298:4203] 当前票数是:73,售出:27,线程名:Thread-2

  2009-11-10 14:25:35.827 SellTickets[1298:4103] 当前票数是:72,售出:28,线程名:Thread-1

  2009-11-10 14:25:35.830 SellTickets[1298:4203] 当前票数是:71,售出:29,线程名:Thread-2

  2009-11-10 14:25:36.329 SellTickets[1298:4103] 当前票数是:70,售出:30,线程名:Thread-1

  2009-11-10 14:25:36.330 SellTickets[1298:4203] 当前票数是:69,售出:31,线程名:Thread-2

  2009-11-10 14:25:36.830 SellTickets[1298:4103] 当前票数是:68,售出:32,线程名:Thread-1

  2009-11-10 14:25:36.831 SellTickets[1298:4203] 当前票数是:67,售出:33,线程名:Thread-2

  2009-11-10 14:25:37.331 SellTickets[1298:4103] 当前票数是:66,售出:34,线程名:Thread-1

  2009-11-10 14:25:37.332 SellTickets[1298:4203] 当前票数是:65,售出:35,线程名:Thread-2

  2009-11-10 14:25:37.832 SellTickets[1298:4103] 当前票数是:64,售出:36,线程名:Thread-1

  2009-11-10 14:25:37.833 SellTickets[1298:4203] 当前票数是:63,售出:37,线程名:Thread-2

  2009-11-10 14:25:38.333 SellTickets[1298:4103] 当前票数是:62,售出:38,线程名:Thread-1

  2009-11-10 14:25:38.334 SellTickets[1298:4203] 当前票数是:61,售出:39,线程名:Thread-2

  2009-11-10 14:25:38.834 SellTickets[1298:4103] 当前票数是:60,售出:40,线程名:Thread-1

  2009-11-10 14:25:38.836 SellTickets[1298:4203] 当前票数是:59,售出:41,线程名:Thread-2

  2009-11-10 14:25:39.335 SellTickets[1298:4103] 当前票数是:58,售出:42,线程名:Thread-1

  2009-11-10 14:25:39.337 SellTickets[1298:4203] 当前票数是:58,售出:42,线程名:Thread-2

  2009-11-10 14:25:39.838 SellTickets[1298:4103] 当前票数是:56,售出:44,线程名:Thread-1

  2009-11-10 14:25:39.839 SellTickets[1298:4203] 当前票数是:55,售出:45,线程名:Thread-2

  2009-11-10 14:25:40.339 SellTickets[1298:4103] 当前票数是:54,售出:46,线程名:Thread-1

  2009-11-10 14:25:40.340 SellTickets[1298:4203] 当前票数是:53,售出:47,线程名:Thread-2

  2009-11-10 14:25:40.840 SellTickets[1298:4103] 当前票数是:52,售出:48,线程名:Thread-1

  2009-11-10 14:25:40.841 SellTickets[1298:4203] 当前票数是:51,售出:49,线程名:Thread-2

  2009-11-10 14:25:41.341 SellTickets[1298:4103] 当前票数是:50,售出:50,线程名:Thread-1

  2009-11-10 14:25:41.342 SellTickets[1298:4203] 当前票数是:49,售出:51,线程名:Thread-2

  2009-11-10 14:25:41.842 SellTickets[1298:4103] 当前票数是:48,售出:52,线程名:Thread-1

  2009-11-10 14:25:41.843 SellTickets[1298:4203] 当前票数是:47,售出:53,线程名:Thread-2

  2009-11-10 14:25:42.343 SellTickets[1298:4103] 当前票数是:46,售出:54,线程名:Thread-1

  2009-11-10 14:25:42.344 SellTickets[1298:4203] 当前票数是:45,售出:55,线程名:Thread-2

  2009-11-10 14:25:42.844 SellTickets[1298:4103] 当前票数是:44,售出:56,线程名:Thread-1

  2009-11-10 14:25:42.845 SellTickets[1298:4203] 当前票数是:43,售出:57,线程名:Thread-2

  2009-11-10 14:25:43.345 SellTickets[1298:4103] 当前票数是:42,售出:58,线程名:Thread-1

  2009-11-10 14:25:43.346 SellTickets[1298:4203] 当前票数是:42,售出:58,线程名:Thread-2

  2009-11-10 14:25:43.846 SellTickets[1298:4103] 当前票数是:40,售出:60,线程名:Thread-1

  2009-11-10 14:25:43.847 SellTickets[1298:4203] 当前票数是:39,售出:61,线程名:Thread-2

  2009-11-10 14:25:44.347 SellTickets[1298:4103] 当前票数是:38,售出:62,线程名:Thread-1

  2009-11-10 14:25:44.348 SellTickets[1298:4203] 当前票数是:37,售出:63,线程名:Thread-2

  2009-11-10 14:25:44.848 SellTickets[1298:4103] 当前票数是:36,售出:64,线程名:Thread-1

  2009-11-10 14:25:44.849 SellTickets[1298:4203] 当前票数是:35,售出:65,线程名:Thread-2

  2009-11-10 14:25:45.349 SellTickets[1298:4103] 当前票数是:34,售出:66,线程名:Thread-1

  2009-11-10 14:25:45.350 SellTickets[1298:4203] 当前票数是:33,售出:67,线程名:Thread-2

  2009-11-10 14:25:45.850 SellTickets[1298:4103] 当前票数是:32,售出:68,线程名:Thread-1

  2009-11-10 14:25:45.851 SellTickets[1298:4203] 当前票数是:31,售出:69,线程名:Thread-2

  2009-11-10 14:25:46.350 SellTickets[1298:4103] 当前票数是:30,售出:70,线程名:Thread-1

  2009-11-10 14:25:46.351 SellTickets[1298:4203] 当前票数是:29,售出:71,线程名:Thread-2

  2009-11-10 14:25:46.851 SellTickets[1298:4103] 当前票数是:28,售出:72,线程名:Thread-1

  2009-11-10 14:25:46.853 SellTickets[1298:4203] 当前票数是:27,售出:73,线程名:Thread-2

  2009-11-10 14:25:47.352 SellTickets[1298:4103] 当前票数是:26,售出:74,线程名:Thread-1

  2009-11-10 14:25:47.354 SellTickets[1298:4203] 当前票数是:25,售出:75,线程名:Thread-2

  可以看到,因为两个线程共享变量tickets和count,开头的输出就产生了异常情况,iphone虽然没有提供类似java下的synchronized关键字,但提供了NSCondition对象接口。查看NSCondition的接口说明可以看出,NSCondition是iphone下的锁对象,所以我们需要让代码成为线程安全的,修改头文件如下:

  //

  // SellTicketsAppDelegate.h

  // SellTickets

  //

  // Created by sun dfsun2009 on 09-11-10.

  // Copyright __MyCompanyName__ 2009. All rights reserved.

  //

  #import 《UIKit/UIKit.h》

  @interface SellTicketsAppDelegate : NSObject 《UIApplicationDelegate》 {

  int tickets;

  int count;

  NSThread* ticketsThreadone;

  NSThread* ticketsThreadtwo;

  NSCondition* ticketsCondition;

  UIWindow *window;

  }

  @property (nonatomic, retain) IBOutlet UIWindow *window;

  @end

  然后在实现中添加如下代码:

  //

  // SellTicketsAppDelegate.m

  // SellTickets

  //

  // Created by sun dfsun2009 on 09-11-10.

  // Copyright __MyCompanyName__ 2009. All rights reserved.

  //

  #import “SellTicketsAppDelegate.h”

  @implementation SellTicketsAppDelegate

  @synthesize window;

  - (void)applicationDidFinishLaunching:(UIApplication *)application {

  tickets = 100;

  count = 0;

  // 锁对象

  ticketCondition = [[NSCondition alloc] init];

  ticketsThreadone = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];

  [ticketsThreadone setName:@“Thread-1”];

  [ticketsThreadone start];

  ticketsThreadtwo = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];

  [ticketsThreadtwo setName:@“Thread-2”];

  [ticketsThreadtwo start];

  //[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];

  // Override point for customization after application launch

  [window makeKeyAndVisible];

  }

  - (void)run{

  while (TRUE) {

  // 上锁

  [ticketsCondition lock];

  if(tickets 》 0)

  {

  [NSThread sleepForTimeInterval:0.5];

  count = 100 - tickets;

  NSLog(@“当前票数是:%d,售出:%d,线程名:%@”,tickets,count,[[NSThread currentThread] name]);

  tickets--;

  }else

  {

  break;

  }

  [ticketsCondition unlock];

  }

  }

  - (void)dealloc {

  [ticketsThreadone release];

  [ticketsThreadtwo release];

  [ticketsCondition release];

  [window release];

  [super dealloc];

  }

  @end

  最后千万别忘记在dealloc方法中调用对象的release进行资源释放,现在再次运行下看看,iphone版本的“售票系统多线程”程序是否跑起来了:)。

此内容为AET网站原创,未经授权禁止转载。