《電子技術應用》
您所在的位置:首頁 > 模擬設計 > 設計應用 > 利用iphone的多線程實現“售票系統(tǒng)”
利用iphone的多線程實現“售票系統(tǒng)”
摘要: 在這篇文章中,筆者就拿大多數Java教程中經典的“售票系統(tǒng)多線程”作為實際例子,在iphone中進行同樣的實現。
Abstract:
Key words :

  Java因為其本身支持多線程而給程序員帶來很多方便,其實在iphone開發(fā)中也支持多線程編程,并且一點也不比java麻煩。

  在這篇文章中,筆者就拿大多數Java教程中經典的“售票系統(tǒng)多線程”作為實際例子,在iphone中進行同樣的實現。

  下面是java版本的“售票系統(tǒng)多線程”代碼:

  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版本的代碼執(zhí)行后控制臺輸出如下:

  當前票數是: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的開發(fā)中也支持多線程編程,并且一點也不比java麻煩。

  在這篇文章中,筆者就拿大多數Java教程中經典的“售票系統(tǒng)多線程”作為實際例子,在iphone中進行同樣的實現。

  下面是java版本的“售票系統(tǒng)多線程”代碼:

  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版本的代碼執(zhí)行后控制臺輸出如下:

  當前票數是: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版本“售票系統(tǒng)多線程”程序中需要設置線程的諸多參數,所以需要采用第一種方法來生成線程對象并自己啟動它們。

  首先,新建一個“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];

 ?。踭icketsThreadone setName:@“Thread-1”];

 ?。踭icketsThreadone start];

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

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

 ?。踭icketsThreadtwo start];

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

  // Override point for customization after application launch

 ?。踳indow makeKeyAndVisible];

  }

  - (void)run{

  while (TRUE) {

  if(tickets 》 0)

  {

 ?。跱SThread sleepForTimeInterval:0.5];

  count = 100 - tickets;

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

  tickets--;

  }else

  {

  break;

  }

  }

  }

  - (void)dealloc {

 ?。踭icketsThreadone release];

 ?。踭icketsThreadtwo release];

  [window release];

 ?。踫uper dealloc];

  }

  @end

  筆者在實現中用alloc初始化了兩個NSThread對象并分別把它們命名為“Thread-1”和“Thread-2”,運行程序可以看到如下輸出:

 ?。跾ession 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];

 ?。踭icketsThreadone setName:@“Thread-1”];

 ?。踭icketsThreadone start];

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

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

 ?。踭icketsThreadtwo start];

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

  // Override point for customization after application launch

  [window makeKeyAndVisible];

  }

  - (void)run{

  while (TRUE) {

  // 上鎖

 ?。踭icketsCondition lock];

  if(tickets 》 0)

  {

 ?。跱SThread sleepForTimeInterval:0.5];

  count = 100 - tickets;

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

  tickets--;

  }else

  {

  break;

  }

  [ticketsCondition unlock];

  }

  }

  - (void)dealloc {

 ?。踭icketsThreadone release];

 ?。踭icketsThreadtwo release];

  [ticketsCondition release];

 ?。踳indow release];

  [super dealloc];

  }

  @end

  最后千萬別忘記在dealloc方法中調用對象的release進行資源釋放,現在再次運行下看看,iphone版本的“售票系統(tǒng)多線程”程序是否跑起來了:)。

此內容為AET網站原創(chuàng),未經授權禁止轉載。