Java因?yàn)槠浔旧碇С?a class="innerlink" href="http://forexkbc.com/tags/多線程" title="多線程" target="_blank">多線程而給程序員帶來(lái)很多方便,,其實(shí)在iphone的開(kāi)發(fā)中也支持多線程編程,,并且一點(diǎn)也不比java麻煩,。
在這篇文章中,,筆者就拿大多數(shù)Java教程中經(jīng)典的“售票系統(tǒng)多線程”作為實(shí)際例子,,在iphone中進(jìn)行同樣的實(shí)現(xiàn)。
下面是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(“當(dāng)前票數(shù)是:”+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í)行后控制臺(tái)輸出如下:
當(dāng)前票數(shù)是:100售出0線程名:t1
當(dāng)前票數(shù)是:99售出1線程名:t2
當(dāng)前票數(shù)是:98售出2線程名:t3
當(dāng)前票數(shù)是:97售出3線程名:t4
當(dāng)前票數(shù)是:96售出4線程名:t1
當(dāng)前票數(shù)是:95售出5線程名:t2
當(dāng)前票數(shù)是:94售出6線程名:t3
當(dāng)前票數(shù)是:93售出7線程名:t4
當(dāng)前票數(shù)是:92售出8線程名:t1
當(dāng)前票數(shù)是:91售出9線程名:t2
當(dāng)前票數(shù)是:90售出10線程名:t3
當(dāng)前票數(shù)是:89售出11線程名:t4
當(dāng)前票數(shù)是:88售出12線程名:t1
當(dāng)前票數(shù)是:87售出13線程名:t2
當(dāng)前票數(shù)是:86售出14線程名:t3
當(dāng)前票數(shù)是:85售出15線程名:t4
當(dāng)前票數(shù)是:84售出16線程名:t1
當(dāng)前票數(shù)是:83售出17線程名:t2
當(dāng)前票數(shù)是:82售出18線程名:t3
當(dāng)前票數(shù)是:81售出19線程名:t4
當(dāng)前票數(shù)是:80售出20線程名:t1
當(dāng)前票數(shù)是:79售出21線程名:t2
當(dāng)前票數(shù)是:78售出22線程名:t3
當(dāng)前票數(shù)是:77售出23線程名:t4
當(dāng)前票數(shù)是:76售出24線程名:t1
當(dāng)前票數(shù)是:75售出25線程名:t2
當(dāng)前票數(shù)是:74售出26線程名:t3
當(dāng)前票數(shù)是:73售出27線程名:t4
……
可以在iphone中進(jìn)行同樣的實(shí)現(xiàn),Iphone的Frameworks/Foundation.framework框架支持多線程編程,,接口定義在:
/Xcode3.1.4/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.1.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSThread.h
到相應(yīng)的目錄下打開(kāi)此文件,,可以看到絕大多數(shù)java中的接口這里也都能找到相應(yīng)的實(shí)現(xiàn),如下:
/* 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因?yàn)槠浔旧碇С侄嗑€程而給程序員帶來(lái)很多方便,,其實(shí)在iphone的開(kāi)發(fā)中也支持多線程編程,,并且一點(diǎn)也不比java麻煩。
在這篇文章中,,筆者就拿大多數(shù)Java教程中經(jīng)典的“售票系統(tǒng)多線程”作為實(shí)際例子,,在iphone中進(jìn)行同樣的實(shí)現(xiàn)。
下面是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(“當(dāng)前票數(shù)是:”+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í)行后控制臺(tái)輸出如下:
當(dāng)前票數(shù)是:100售出0線程名:t1
當(dāng)前票數(shù)是:99售出1線程名:t2
當(dāng)前票數(shù)是:98售出2線程名:t3
當(dāng)前票數(shù)是:97售出3線程名:t4
當(dāng)前票數(shù)是:96售出4線程名:t1
當(dāng)前票數(shù)是:95售出5線程名:t2
當(dāng)前票數(shù)是:94售出6線程名:t3
當(dāng)前票數(shù)是:93售出7線程名:t4
當(dāng)前票數(shù)是:92售出8線程名:t1
當(dāng)前票數(shù)是:91售出9線程名:t2
當(dāng)前票數(shù)是:90售出10線程名:t3
當(dāng)前票數(shù)是:89售出11線程名:t4
當(dāng)前票數(shù)是:88售出12線程名:t1
當(dāng)前票數(shù)是:87售出13線程名:t2
當(dāng)前票數(shù)是:86售出14線程名:t3
當(dāng)前票數(shù)是:85售出15線程名:t4
當(dāng)前票數(shù)是:84售出16線程名:t1
當(dāng)前票數(shù)是:83售出17線程名:t2
當(dāng)前票數(shù)是:82售出18線程名:t3
當(dāng)前票數(shù)是:81售出19線程名:t4
當(dāng)前票數(shù)是:80售出20線程名:t1
當(dāng)前票數(shù)是:79售出21線程名:t2
當(dāng)前票數(shù)是:78售出22線程名:t3
當(dāng)前票數(shù)是:77售出23線程名:t4
當(dāng)前票數(shù)是:76售出24線程名:t1
當(dāng)前票數(shù)是:75售出25線程名:t2
當(dāng)前票數(shù)是:74售出26線程名:t3
當(dāng)前票數(shù)是:73售出27線程名:t4
……
可以在iphone中進(jìn)行同樣的實(shí)現(xiàn),,Iphone的Frameworks/Foundation.framework框架支持多線程編程,接口定義在:
/Xcode3.1.4/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.1.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSThread.h
到相應(yīng)的目錄下打開(kāi)此文件,,可以看到絕大多數(shù)java中的接口這里也都能找到相應(yīng)的實(shí)現(xiàn),,如下:
/* 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和大多數(shù)iphone的接口對(duì)象一樣,,有兩種方式可以初始化:
一種使用initWithTarget :(id)target selector:(SEL)selector object:(id)argument,,但需要負(fù)責(zé)在對(duì)象的retain count為0時(shí)調(diào)用對(duì)象的release方法清理對(duì)象。
另一種則使用所謂的convenient method,,這個(gè)方便接口就是detachNewThreadSelector,,這個(gè)方法可以直接生成一個(gè)線程并啟動(dòng)它,,而且無(wú)需為線程的清理負(fù)責(zé)。
因?yàn)樵诠P者的iphone版本“售票系統(tǒng)多線程”程序中需要設(shè)置線程的諸多參數(shù),,所以需要采用第一種方法來(lái)生成線程對(duì)象并自己?jiǎn)?dòng)它們,。
首先,新建一個(gè)“Window-based Application”項(xiàng)目,,并命名為SellTickets,,接下來(lái)在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
筆者在頭文件中聲明了兩個(gè)NSThread的指針,,下面需要在*.m文件中初始化并實(shí)現(xiàn)它們,,如下:
//
// 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”];
?。踭icketsThreadone start];
ticketsThreadtwo = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
?。踭icketsThreadtwo setName:@“Thread-2”];
[ticketsThreadtwo 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āng)前票數(shù)是:%d,售出:%d,,線程名:%@”,,tickets,count,,[[NSThread currentThread] name]);
tickets--;
}else
{
break;
}
}
}
- (void)dealloc {
?。踭icketsThreadone release];
[ticketsThreadtwo release];
?。踳indow release];
?。踫uper dealloc];
}
@end
筆者在實(shí)現(xiàn)中用alloc初始化了兩個(gè)NSThread對(duì)象并分別把它們命名為“Thread-1”和“Thread-2”,運(yùn)行程序可以看到如下輸出:
?。跾ession started at 2009-11-10 14:25:26 +0800.]
2009-11-10 14:25:28.814 SellTickets[1298:4103] 當(dāng)前票數(shù)是:100,,售出:0,線程名:Thread-1
2009-11-10 14:25:28.814 SellTickets[1298:4203] 當(dāng)前票數(shù)是:100,,售出:0,,線程名:Thread-2
2009-11-10 14:25:29.316 SellTickets[1298:4103] 當(dāng)前票數(shù)是:98,售出:2,,線程名:Thread-1
2009-11-10 14:25:29.316 SellTickets[1298:4203] 當(dāng)前票數(shù)是:98,,售出:2,線程名:Thread-2
2009-11-10 14:25:29.817 SellTickets[1298:4103] 當(dāng)前票數(shù)是:96,,售出:4,,線程名:Thread-1
2009-11-10 14:25:29.817 SellTickets[1298:4203] 當(dāng)前票數(shù)是:96,售出:4,,線程名:Thread-2
2009-11-10 14:25:30.318 SellTickets[1298:4103] 當(dāng)前票數(shù)是:94,,售出:6,,線程名:Thread-1
2009-11-10 14:25:30.318 SellTickets[1298:4203] 當(dāng)前票數(shù)是:94,售出:6,,線程名:Thread-2
2009-11-10 14:25:30.819 SellTickets[1298:4103] 當(dāng)前票數(shù)是:92,,售出:8,線程名:Thread-1
2009-11-10 14:25:30.819 SellTickets[1298:4203] 當(dāng)前票數(shù)是:92,,售出:8,,線程名:Thread-2
2009-11-10 14:25:31.320 SellTickets[1298:4103] 當(dāng)前票數(shù)是:90,售出:10,,線程名:Thread-1
2009-11-10 14:25:31.320 SellTickets[1298:4203] 當(dāng)前票數(shù)是:90,,售出:10,線程名:Thread-2
2009-11-10 14:25:31.820 SellTickets[1298:4103] 當(dāng)前票數(shù)是:88,,售出:12,,線程名:Thread-1
2009-11-10 14:25:31.821 SellTickets[1298:4203] 當(dāng)前票數(shù)是:87,售出:13,,線程名:Thread-2
2009-11-10 14:25:32.321 SellTickets[1298:4103] 當(dāng)前票數(shù)是:86,售出:14,,線程名:Thread-1
2009-11-10 14:25:32.322 SellTickets[1298:4203] 當(dāng)前票數(shù)是:86,,售出:14,線程名:Thread-2
2009-11-10 14:25:32.823 SellTickets[1298:4103] 當(dāng)前票數(shù)是:84,,售出:16,,線程名:Thread-1
2009-11-10 14:25:32.823 SellTickets[1298:4203] 當(dāng)前票數(shù)是:83,售出:17,,線程名:Thread-2
2009-11-10 14:25:33.323 SellTickets[1298:4103] 當(dāng)前票數(shù)是:82,,售出:18,線程名:Thread-1
2009-11-10 14:25:33.324 SellTickets[1298:4203] 當(dāng)前票數(shù)是:81,,售出:19,,線程名:Thread-2
2009-11-10 14:25:33.824 SellTickets[1298:4103] 當(dāng)前票數(shù)是:80,售出:20,,線程名:Thread-1
2009-11-10 14:25:33.825 SellTickets[1298:4203] 當(dāng)前票數(shù)是:79,,售出:21,線程名:Thread-2
2009-11-10 14:25:34.325 SellTickets[1298:4103] 當(dāng)前票數(shù)是:78,,售出:22,,線程名:Thread-1
2009-11-10 14:25:34.326 SellTickets[1298:4203] 當(dāng)前票數(shù)是:77,售出:23,,線程名:Thread-2
2009-11-10 14:25:34.826 SellTickets[1298:4103] 當(dāng)前票數(shù)是:76,,售出:24,線程名:Thread-1
2009-11-10 14:25:34.827 SellTickets[1298:4203] 當(dāng)前票數(shù)是:75,,售出:25,,線程名:Thread-2
2009-11-10 14:25:35.327 SellTickets[1298:4103] 當(dāng)前票數(shù)是:74,,售出:26,線程名:Thread-1
2009-11-10 14:25:35.328 SellTickets[1298:4203] 當(dāng)前票數(shù)是:73,,售出:27,,線程名:Thread-2
2009-11-10 14:25:35.827 SellTickets[1298:4103] 當(dāng)前票數(shù)是:72,售出:28,,線程名:Thread-1
2009-11-10 14:25:35.830 SellTickets[1298:4203] 當(dāng)前票數(shù)是:71,,售出:29,線程名:Thread-2
2009-11-10 14:25:36.329 SellTickets[1298:4103] 當(dāng)前票數(shù)是:70,,售出:30,,線程名:Thread-1
2009-11-10 14:25:36.330 SellTickets[1298:4203] 當(dāng)前票數(shù)是:69,售出:31,,線程名:Thread-2
2009-11-10 14:25:36.830 SellTickets[1298:4103] 當(dāng)前票數(shù)是:68,,售出:32,線程名:Thread-1
2009-11-10 14:25:36.831 SellTickets[1298:4203] 當(dāng)前票數(shù)是:67,,售出:33,,線程名:Thread-2
2009-11-10 14:25:37.331 SellTickets[1298:4103] 當(dāng)前票數(shù)是:66,售出:34,,線程名:Thread-1
2009-11-10 14:25:37.332 SellTickets[1298:4203] 當(dāng)前票數(shù)是:65,,售出:35,線程名:Thread-2
2009-11-10 14:25:37.832 SellTickets[1298:4103] 當(dāng)前票數(shù)是:64,,售出:36,,線程名:Thread-1
2009-11-10 14:25:37.833 SellTickets[1298:4203] 當(dāng)前票數(shù)是:63,售出:37,,線程名:Thread-2
2009-11-10 14:25:38.333 SellTickets[1298:4103] 當(dāng)前票數(shù)是:62,,售出:38,線程名:Thread-1
2009-11-10 14:25:38.334 SellTickets[1298:4203] 當(dāng)前票數(shù)是:61,,售出:39,,線程名:Thread-2
2009-11-10 14:25:38.834 SellTickets[1298:4103] 當(dāng)前票數(shù)是:60,售出:40,,線程名:Thread-1
2009-11-10 14:25:38.836 SellTickets[1298:4203] 當(dāng)前票數(shù)是:59,,售出:41,線程名:Thread-2
2009-11-10 14:25:39.335 SellTickets[1298:4103] 當(dāng)前票數(shù)是:58,,售出:42,,線程名:Thread-1
2009-11-10 14:25:39.337 SellTickets[1298:4203] 當(dāng)前票數(shù)是:58,售出:42,,線程名:Thread-2
2009-11-10 14:25:39.838 SellTickets[1298:4103] 當(dāng)前票數(shù)是:56,,售出:44,線程名:Thread-1
2009-11-10 14:25:39.839 SellTickets[1298:4203] 當(dāng)前票數(shù)是:55,售出:45,,線程名:Thread-2
2009-11-10 14:25:40.339 SellTickets[1298:4103] 當(dāng)前票數(shù)是:54,,售出:46,線程名:Thread-1
2009-11-10 14:25:40.340 SellTickets[1298:4203] 當(dāng)前票數(shù)是:53,,售出:47,,線程名:Thread-2
2009-11-10 14:25:40.840 SellTickets[1298:4103] 當(dāng)前票數(shù)是:52,售出:48,,線程名:Thread-1
2009-11-10 14:25:40.841 SellTickets[1298:4203] 當(dāng)前票數(shù)是:51,,售出:49,線程名:Thread-2
2009-11-10 14:25:41.341 SellTickets[1298:4103] 當(dāng)前票數(shù)是:50,,售出:50,,線程名:Thread-1
2009-11-10 14:25:41.342 SellTickets[1298:4203] 當(dāng)前票數(shù)是:49,售出:51,,線程名:Thread-2
2009-11-10 14:25:41.842 SellTickets[1298:4103] 當(dāng)前票數(shù)是:48,,售出:52,線程名:Thread-1
2009-11-10 14:25:41.843 SellTickets[1298:4203] 當(dāng)前票數(shù)是:47,,售出:53,,線程名:Thread-2
2009-11-10 14:25:42.343 SellTickets[1298:4103] 當(dāng)前票數(shù)是:46,售出:54,,線程名:Thread-1
2009-11-10 14:25:42.344 SellTickets[1298:4203] 當(dāng)前票數(shù)是:45,,售出:55,線程名:Thread-2
2009-11-10 14:25:42.844 SellTickets[1298:4103] 當(dāng)前票數(shù)是:44,,售出:56,線程名:Thread-1
2009-11-10 14:25:42.845 SellTickets[1298:4203] 當(dāng)前票數(shù)是:43,,售出:57,,線程名:Thread-2
2009-11-10 14:25:43.345 SellTickets[1298:4103] 當(dāng)前票數(shù)是:42,售出:58,,線程名:Thread-1
2009-11-10 14:25:43.346 SellTickets[1298:4203] 當(dāng)前票數(shù)是:42,,售出:58,線程名:Thread-2
2009-11-10 14:25:43.846 SellTickets[1298:4103] 當(dāng)前票數(shù)是:40,,售出:60,,線程名:Thread-1
2009-11-10 14:25:43.847 SellTickets[1298:4203] 當(dāng)前票數(shù)是:39,售出:61,,線程名:Thread-2
2009-11-10 14:25:44.347 SellTickets[1298:4103] 當(dāng)前票數(shù)是:38,,售出:62,線程名:Thread-1
2009-11-10 14:25:44.348 SellTickets[1298:4203] 當(dāng)前票數(shù)是:37,,售出:63,,線程名:Thread-2
2009-11-10 14:25:44.848 SellTickets[1298:4103] 當(dāng)前票數(shù)是:36,售出:64,線程名:Thread-1
2009-11-10 14:25:44.849 SellTickets[1298:4203] 當(dāng)前票數(shù)是:35,,售出:65,,線程名:Thread-2
2009-11-10 14:25:45.349 SellTickets[1298:4103] 當(dāng)前票數(shù)是:34,售出:66,,線程名:Thread-1
2009-11-10 14:25:45.350 SellTickets[1298:4203] 當(dāng)前票數(shù)是:33,,售出:67,線程名:Thread-2
2009-11-10 14:25:45.850 SellTickets[1298:4103] 當(dāng)前票數(shù)是:32,,售出:68,,線程名:Thread-1
2009-11-10 14:25:45.851 SellTickets[1298:4203] 當(dāng)前票數(shù)是:31,售出:69,,線程名:Thread-2
2009-11-10 14:25:46.350 SellTickets[1298:4103] 當(dāng)前票數(shù)是:30,,售出:70,線程名:Thread-1
2009-11-10 14:25:46.351 SellTickets[1298:4203] 當(dāng)前票數(shù)是:29,,售出:71,,線程名:Thread-2
2009-11-10 14:25:46.851 SellTickets[1298:4103] 當(dāng)前票數(shù)是:28,售出:72,,線程名:Thread-1
2009-11-10 14:25:46.853 SellTickets[1298:4203] 當(dāng)前票數(shù)是:27,,售出:73,線程名:Thread-2
2009-11-10 14:25:47.352 SellTickets[1298:4103] 當(dāng)前票數(shù)是:26,,售出:74,,線程名:Thread-1
2009-11-10 14:25:47.354 SellTickets[1298:4203] 當(dāng)前票數(shù)是:25,售出:75,,線程名:Thread-2
可以看到,,因?yàn)閮蓚€(gè)線程共享變量tickets和count,開(kāi)頭的輸出就產(chǎn)生了異常情況,,iphone雖然沒(méi)有提供類似java下的synchronized關(guān)鍵字,,但提供了NSCondition對(duì)象接口。查看NSCondition的接口說(shuō)明可以看出,,NSCondition是iphone下的鎖對(duì)象,,所以我們需要讓代碼成為線程安全的,修改頭文件如下:
//
// 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
然后在實(shí)現(xiàn)中添加如下代碼:
//
// 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;
// 鎖對(duì)象
ticketCondition = [[NSCondition alloc] init];
ticketsThreadone = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
?。踭icketsThreadone setName:@“Thread-1”];
[ticketsThreadone start];
ticketsThreadtwo = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
?。踭icketsThreadtwo 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āng)前票數(shù)是:%d,售出:%d,線程名:%@”,,tickets,,count,[[NSThread currentThread] name]);
tickets--;
}else
{
break;
}
?。踭icketsCondition unlock];
}
}
- (void)dealloc {
?。踭icketsThreadone release];
[ticketsThreadtwo release];
?。踭icketsCondition release];
?。踳indow release];
[super dealloc];
}
@end
最后千萬(wàn)別忘記在dealloc方法中調(diào)用對(duì)象的release進(jìn)行資源釋放,,現(xiàn)在再次運(yùn)行下看看,,iphone版本的“售票系統(tǒng)多線程”程序是否跑起來(lái)了:)。