当前位置:  编程技术>移动开发
本页文章导读:
    ▪Gesture建立手写笔划图案        Gesture建立手写笔画图案 添加权限   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />   MyGesture.java   private Gesture ges; private GestureLibrary lib; private GestureOverlayView overlay; private B.........
    ▪ ProgressBar播发动画        ProgressBar播放动画 1. 布局文件中 <ProgressBar android:id="@+id/ProgressBar01" android:layout_width="250dip" android:layout_height="300dip" android:layout_marginLeft="27dip" />   2. styles.xml <?xml version="1.........
    ▪ NSThread线程有关       NSThread线程相关   使用performSelectorOnMainThread进行ui的更新:[self performSelectorOnMainThread:@selector(refresh) withObject:nil waitUntilDone:NO];//------------ MoneyCat 22:59:15 performSelectorInBackground:(SEL) withObject:(id) .........

[1]Gesture建立手写笔划图案
    来源: 互联网  发布时间: 2014-02-18
Gesture建立手写笔画图案

添加权限

 

<uses-permission
		android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 

MyGesture.java

 

private Gesture ges;
	private GestureLibrary lib;
	private GestureOverlayView overlay;
	private Button button01, button02 , button03;
	private EditText et;
	private String gesPath;

	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.my_gesture);

		/* 查看SDCard是否存在 */
		if (!Environment.MEDIA_MOUNTED.equals(Environment
				.getExternalStorageState())) {
			/* SD卡不存在,显示Toast信息 */
			toast("SD卡不存在!程序无法运行");
		}
		/* 以findViewById()取得对象 */
		et = (EditText) this.findViewById(R.id.myEditText1);
		button01 = (Button) this.findViewById(R.id.myButton1);
		button02 = (Button) this.findViewById(R.id.myButton2);
		button03 = (Button) this.findViewById(R.id.myButton3);
		overlay = (GestureOverlayView) findViewById(R.id.myGestures1);

		/* 取得GestureLibrary的文件路径 */
		gesPath = new File(Environment.getExternalStorageDirectory(),
				"gestures").getAbsolutePath();

		/* 设置EditText的OnKeyListener */
		et.setOnKeyListener(new EditText.OnKeyListener() {
			public boolean onKey(View v, int keyCode, KeyEvent event) {
				/* 名称与手写都已设置时将新增的Button enable */
				if (ges != null && et.getText().length() != 0) {
					button01.setEnabled(true);
				} else {
					button01.setEnabled(false);
				}
				return false;
			}
		});

		/* 设定Overlay的OnGestureListener */
		overlay.addOnGestureListener(new GestureOverlayView.OnGestureListener() {
			public void onGesture(GestureOverlayView overlay, MotionEvent event) {
			}

			/* 开始画手势时将新增的Button disable,并清除Gesture */
			public void onGestureStarted(GestureOverlayView overlay,
					MotionEvent event) {
				button01.setEnabled(false);
				ges = null;
			}

			/* 手势画完时判断名称与手写是否完整建立 */
			public void onGestureEnded(GestureOverlayView overlay,
					MotionEvent event) {
				ges = overlay.getGesture();
				if (ges != null && et.getText().length() != 0) {
					button01.setEnabled(true);
				}
			}

			public void onGestureCancelled(GestureOverlayView overlay,
					MotionEvent event) {
			}
		});

		/* 设定button01的OnClickListener */
		button01.setOnClickListener(new Button.OnClickListener() {
			public void onClick(View v) {
				final String gesName = et.getText().toString();
				try {
					File file = new File(gesPath);
					lib = GestureLibraries.fromFile(gesPath);

					if (!file.exists()) {
						/* 文件不存在就直接写入 */
						lib.addGesture(gesName, ges);
						if (lib.save()) {
							/* 将设定画面数据清除 */
							et.setText("");
							button01.setEnabled(false);
							overlay.clear(true);
							/* 保存成功,显示Toast信息 */
							toast("保存成功,保存路径为:" + gesPath);
						} else {
							/* 保存失败,显示Toast信息 */
							toast("保存失败");
						}
					} else {
						/* 文件存在时因读取保存的Gesture */
						if (!lib.load()) {
							/* Library读取失败,显示Toast讯息 */
							toast("Library读取失败");
						} else {
							/* 如果Library中存在相同名称,则因将其移除再写入 */
							final Set<String> en = lib.getGestureEntries();
							if (en.contains(gesName)) {
								new AlertDialog.Builder(MyGesture.this)
										.setTitle("提醒")
										.setMessage("文件已存在,确定要覆盖吗?")
										.setNegativeButton("取消", null)
										.setPositiveButton(
												"确定",
												new DialogInterface.OnClickListener() {
													public void onClick(
															DialogInterface dialoginterface,
															int i) {
														ArrayList<Gesture> al = lib
																.getGestures(gesName);
														for (int t = 0; t < al
																.size(); t++) {
															lib.removeGesture(
																	gesName,
																	al.get(t));
														}
														lib.addGesture(gesName,
																ges);
														if (lib.save()) {
															/* 将设定画面数据清除 */
															et.setText("");
															button01.setEnabled(false);
															overlay.clear(true);
															/* 保存成功,显示Toast信息 */
															toast("保存成功,保存路径为:"
																	+ gesPath);
														} else {
															/* 保存失败,显示Toast信息 */
															toast("保存失败");
														}
													}
												}).show();
							} else {
								lib.addGesture(gesName, ges);
								if (lib.save()) {
									/* 将设定画面数据清除 */
									et.setText("");
									button01.setEnabled(false);
									overlay.clear(true);
									/* 保存成功,显示Toast信息 */
									toast("保存成功,保存路径为:" + gesPath);
								} else {
									/* 保存失败,显示Toast信息 */
									toast("保存失败");
								}
							}
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
		/* 设置button02的OnClickListener */
		button02.setOnClickListener(new Button.OnClickListener() {
			public void onClick(View v) {
				et.setText("");
				button01.setEnabled(false);
				overlay.clear(true);
			}
		});
		button03.setOnClickListener(new OnClickListener(){

			public void onClick(View v) {
				Intent intent = new Intent(MyGesture.this , ReadGesture.class);
				startActivity(intent);
			}
			
		});
	}

	public void toast(String str) {
		Toast.makeText(MyGesture.this, str, Toast.LENGTH_LONG).show();
	}

 ReadGesture.java

 

private SimpleAdapter listItemAdapter; // ListView的适配器
	private ArrayList<HashMap<String, Object>> listItem; // ListView的数据源,这里是一个HashMap的列表
	private ListView myList; // ListView控件
	
	private List<Gesture> gesList;

	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.phone_info);
		
		listItem = new ArrayList<HashMap<String, Object>>();
		listItemAdapter = new SimpleAdapter(this, listItem, R.layout.list_item3,
				new String[] { "image", "text" }, new int[] { R.id.imageView1,
						R.id.textView1 });
		myList = (ListView) findViewById(R.id.listView1);
		myList.setAdapter(listItemAdapter);
		
		gesList = new ArrayList<Gesture>();
		
		try{
			String gesPath = new File(Environment.getExternalStorageDirectory(),
				"gestures").getAbsolutePath();
			File gesFile = new File(gesPath);
			GestureLibrary lib = GestureLibraries.fromFile(gesFile);
			if(gesFile.exists()){
				if(!lib.load()){
					toast("读取Library失败");
				}
				else{
					Object[] entries = lib.getGestureEntries().toArray();
					for(int i = 0 ; i < entries.length ; i++){
						ArrayList<Gesture> gestureArray = lib.getGestures(entries[i].toString());
						for(int j = 0; j < gestureArray.size() ; j++){
							String gestureName = entries[i].toString();
							addItem(R.drawable.doc,gestureName);
							Gesture gesture = (Gesture)gestureArray.get(j);
							gesList.add(gesture);
						}
					}
				}
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		
		myList.setOnItemClickListener(new OnItemClickListener() {

			public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
					long arg3) {
				Bitmap bitmap = gesList.get(arg2).toBitmap(64, 64, 12, Color.BLUE);
				ImageView gesImage = new ImageView(ReadGesture.this);
				gesImage.setImageBitmap(bitmap);
				new AlertDialog.Builder(ReadGesture.this)
				.setTitle("查看Gesture")
				.setView(gesImage)
				.setPositiveButton("确定",
						new DialogInterface.OnClickListener() {
							public void onClick(
									DialogInterface dialoginterface,
									int i) {
								dialoginterface.cancel();
							}
						}).show();
			}
			
		});
	}
	
	private void addItem(int image, String str) {
		HashMap<String, Object> map = new HashMap<String, Object>();
		map.put("image", image);
		map.put("text", str);
		listItem.add(map);
		listItemAdapter.notifyDataSetChanged();
	}
	
	public void toast(String str) {
		Toast.makeText(ReadGesture.this, str, Toast.LENGTH_LONG).show();
	}




 

 


    
[2] ProgressBar播发动画
    来源: 互联网  发布时间: 2014-02-18
ProgressBar播放动画

1.

布局文件中

   <ProgressBar 
		android:id="@+id/ProgressBar01" 
		     
		android:layout_width="250dip"
		android:layout_height="300dip"
		android:layout_marginLeft="27dip"
		/>

 

2.

styles.xml

<?xml version="1.0" encoding="UTF-8"?> 
<resources>


<style name="animStyle" parent="@android:style/Widget.ProgressBar.Large"> 
        <item name="android:indeterminateDrawable">@anim/loading_anim</item>   
    </style>

</resources>

 

3.

loading_anim.xml

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
				android:oneshot="true"
				>
	<item android:drawable="@drawable/loading_pic0001" android:duration="85"/>
	<item android:drawable="@drawable/loading_pic0002" android:duration="85"/>
	<item android:drawable="@drawable/loading_pic0003" android:duration="85"/>
	<item android:drawable="@drawable/loading_pic0004" android:duration="85"/>
	<item android:drawable="@drawable/loading_pic0005" android:duration="85"/>
	<item android:drawable="@drawable/loading_pic0006" android:duration="85"/>
</animation-list>
 

    
[3] NSThread线程有关
    来源: 互联网  发布时间: 2014-02-18
NSThread线程相关

 

使用performSelectorOnMainThread进行ui的更新:

[self performSelectorOnMainThread:@selector(refresh) withObject:nil waitUntilDone:NO];

//------------
MoneyCat  22:59:15
performSelectorInBackground:(SEL) withObject:(id) 或
NSThread detachNewThreadSelector:(SEL )toTarget:(id) withObject:(id) 启动一个新线程,两者没多大差别,具体看你习惯哪种。
用 performSelectorOnMainThread:(SEL) withObjec:(id) 回调。
                    Dodo  23:00:11
我就是用NSThread detachNewThreadSelector:(SEL )toTarget:(id) withObject:(id) 的...
MoneyCat  23:00:35
在 pool release 之前
                    Dodo  23:01:32
performSelectorOnMainThread:(SEL) withObjec:(id) 这个和那两个有区别么...
MoneyCat  23:02:04
如,主线程中有一个静态类 AppAPI的话。即
AppAPI performSelectorOnMainThread:(@selector(XXX)):withObject(NSNumber numberWithInt:(123))
performSelectorOnMainThread:是用来在线程中访问主线程的方法的。
MoneyCat  23:03:04
比如你在MainViewController中开了一个线程。
在这个新线程中,想要再访问MainViewController中的某些对象或是函数,如果直接的 MainViewController setTag 是不行的。
MoneyCat  23:04:11
虽然有办法但没有使用performSelectorOnMainThread好,且安全。
                    Dodo  23:04:15
额.需要消化下.
performSelectorOnMainThread 这个没开启新线程吧.
                    Dodo  23:06:44

MoneyCat  23:08:22
例:MainViewController中 开线程是:
[self performSelectorInBackground:(@selector(StartThread:)) withObject:(self)];
在StartThread中即是
- (void) StartThread:(id)delegate
{ 
  [delegate performSelectorOnMainThread:(@selector(CallbackFunction:)) withObject:(newValue)];
}

- (void) CallbackFunction:(id)newValue
{
   textFiled.text = newValue.Name;
}

MoneyCat  23:08:55
看清楚。。。 OnMianThread是用于回调的。
detachNewThreadSelector 才是开新线程。
MoneyCat  23:10:47
我比如喜欢使用 performSelectorInBackground 来开线程,detachNewThreadSelector 的 toTarget:参数如果是一个静态类的话,得 AppAPI self 多打几个字符。有点麻烦。
上面的简例应该足够说明了。呵呵。慢慢看下吧。。
                    Dodo  23:11:53
嗯.谢谢师父
MoneyCat  23:12:10
不客气。。
 //----------------------------------
以下原文:
http://mmz06.blog.163.com/blog/static/12141696201111641741284/

多线程在各种编程语言中都是难点,很多语言中实现起来很麻烦,objective-c虽然源于c,但其多线程编程却相当简单,可以与java相媲美。这篇文章主要从线程创建与启动、线程的同步与锁、线程的交互、线程池等等四个方面简单的讲解一下iphone中的多线程编程。

一、线程创建与启动

线程创建主要有二种方式:

- (id)init; // designated initializer - (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument;

当然,还有一种比较特殊,就是使用所谓的convenient method,这个方法可以直接生成一个线程并启动它,而且无需为线程的清理负责。这个方法的接口是:

+ (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument

前两种方法创建后,需要手机启动,启动的方法是:

- (void)start;

二、线程的同步与锁
要说明线程的同步与锁,最好的例子可能就是多个窗口同时售票的售票系统了。我们知道在java中,使用synchronized来同步,而iphone虽然没有提供类似java下的synchronized关键字,但提供了NSCondition对象接口。查看NSCondition的接口说明可以看出,NSCondition是iphone下的锁对象,所以我们可以使用NSCondition实现iphone中的线程安全。这是来源于网上的一个例子:
SellTicketsAppDelegate.h 文件

// SellTicketsAppDelegate.h 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 文件

// SellTicketsAppDelegate.m 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

三、线程的交互
线程在运行过程中,可能需要与其它线程进行通信,如在主线程中修改界面等等,可以使用如下接口:

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

由于在本过程中,可能需要释放一些资源,则需要使用NSAutoreleasePool来进行管理,如:

- (void)startTheBackgroundJob { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // to do something in your thread job ... [self performSelectorOnMainThread:@selector(makeMyProgressBarMoving) withObject:nil waitUntilDone:NO]; [pool release]; }

 

 

 

IOS4 已经支持多线程了,我的EASYWEB在打开多个网页时会卡得要命,决定把它改成多线程方式进行加载网页
IOS4的多线程,基于Objective-c 相对 C++ JAVA来说简单不少

技术要点:
一 线程创建与启动
线程类 NSThread

包含如下线程操作方法:

 //返回当前线程
+ (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;

// 线程属性值
+ (double)threadPriority ;
+ (BOOL)setThreadPriority:(double)p ;

// 线程函数地址
+ (NSArray *)callStackReturnAddresses;

// 设置与返回线程名称
- (void)setName:(NSString *)n;
- (NSString *)name;

// 线程堆栈
- (NSUInteger)stackSize;
- (void)setStackSize:(NSUInteger)s;

// 判断当前线程是否为主线程
- (BOOL)isMainThread;
+ (BOOL)isMainThread;

+ (NSThread *)mainThread;

// 线程对象初始化操作   (通过创建线程对象 ,需要 手工指定线程函数与各种属性)
- (id)init;

// 在线程对象初始化时创建一个线程(指定线程函数)
- (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


推荐方式

// 通过类方法创建一个线程
+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument;

// 在线程对象初始化时创建一个线程(指定线程函数)
- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument;

主要通过selector:(SEL)selector 指定个功能函数,系统使其与主线程分开运行,以达到多线程的效果.

以上方式创建线程,非类方法创建需要调用 start才能让线程真正运行起来.

当多个线程同时运行,就会出现访问资源的同步问题

二 线程同步操作

IPHONE 使用NSCondition来进行线程同步,它是IPHONE的锁对象,用来保护当前访问的资源.

大致使用方法 
NSCondition* mYLock = [[NSCondition alloc] init];

[mYLock lock]

资源....

[mYLock unLock];

[mYLock release];

三 线程的交互
 
使用线程对象的
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait
进行交互操作
主要是调用 主线程中指定的方法来执行一些相关操作

四 线程池 NSOperation
NSInvocationOperation是 NSOperation的子类 具体使用代码

// 建立一个操作对象 
NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(myTaskMethod:) object:data];

// 将操作对象 加到系统已经的操作对列里, 这时候 myTaskMethod以一个线程的方式与主线程分开执行.
[[MyAppDelegate sharedOperationQueue] addOperation:theOp];

// 这个是真正运行在另外一个线程的“方法”
- (void)myTaskMethod:(id)data
{
    // Perform the task.
}

以上是使用系统操作对列,可以使用 NSOperationQueue创建自己的线程对列

NSOperationQueue *operationQueue; 
        operationQueue = [[NSOperationQueue alloc] init]; //初始化操作队列
        [operationQueue setMaxConcurrentOperationCount:n]; // 可以设置队列的个数
        [operationQueue addOperation:otherOper];

线程创建与撤销遵循 OC的内存管理规则.


以下原文:http://www.cnblogs.com/kesalin/archive/2011/08/18/cocoa_thread.html

iOS 支持多个层次的多线程编程,层次越高的抽象程度越高,使用起来也越方便,也是苹果最推荐使用的方法。下面根据抽象层次从低到高依次列出iOS所支持的多线程编程范式:

1, Thread;
2, Cocoa operations;
3, Grand Central Dispatch (GCD) (iOS4 才开始支持)


下面简要说明这三种不同范式:

Thread 是这三种范式里面相对轻量级的,但也是使用起来最负责的,你需要自己管理thread的生命周期,线程之间的同步。线程共享同一应用程序的部分内存空间,它们拥有对数据相同的访问权限。你得协调多个线程对同一数据的访问,一般做法是在访问之前加锁,这会导致一定的性能开销。在 iOS 中我们可以使用多种形式的 thread:

Cocoa threads: 使用NSThread 或直接从 NSObject 的类方法 performSelectorInBackground:withObject: 来创建一个线程。如果你选择thread来实现多线程,那么 NSThread 就是官方推荐优先选用的方式。
POSIX threads: 基于 C 语言的一个多线程库,

Cocoa operations是基于 Obective-C实现的,类 NSOperation 以面向对象的方式封装了用户需要执行的操作,我们只要聚焦于我们需要做的事情,而不必太操心线程的管理,同步等事情,因为NSOperation已经为我们封装了这些事情。 NSOperation 是一个抽象基类,我们必须使用它的子类。iOS 提供了两种默认实现:NSInvocationOperation 和 NSBlockOperation。

Grand Central Dispatch (GCD): iOS4 才开始支持,它提供了一些新的特性,以及运行库来支持多核并行编程,它的关注点更高:如何在多个 cpu 上提升效率。

有了上面的总体框架,我们就能清楚地知道不同方式所处的层次以及可能的效率,便利性差异。下面我们先来看看 NSThread 的使用,包括创建,启动,同步,通信等相关知识。这些与 win32/Java 下的 thread 使用非常相似。

线程创建与启动

NSThread的创建主要有两种直接方式:

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

NSThread* myThread = [[NSThread alloc] initWithTarget:self
                                        selector:@selector(myThreadMainMethod:)
                                        object:nil];
[myThread start];


这两种方式的区别是:前一种一调用就会立即创建一个线程来做事情;而后一种虽然你 alloc 了也 init了,但是要直到我们手动调用 start 启动线程时才会真正去创建线程。这种延迟实现思想在很多跟资源相关的地方都有用到。后一种方式我们还可以在启动线程之前,对线程进行配置,比如设置 stack 大小,线程优先级。

还有一种间接的方式,更加方便,我们甚至不需要显式编写 NSThread 相关代码。那就是利用 NSObject 的类方法 performSelectorInBackground:withObject: 来创建一个线程:

[myObj performSelectorInBackground:@selector(myThreadMainMethod) withObject:nil];

其效果与 NSThread 的 detachNewThreadSelector:toTarget:withObject: 是一样的。

线程同步

线程的同步方法跟其他系统下类似,我们可以用原子操作,可以用 mutex,lock等。
iOS的原子操作函数是以 OSAtomic开头的,比如:OSAtomicAdd32, OSAtomicOr32等等。这些函数可以直接使用,因为它们是原子操作。

iOS中的 mutex 对应的是 NSLock,它遵循 NSLooking协议,我们可以使用 lock, tryLock, lockBeforeData:来加锁,用 unLock来解锁。使用示例:

BOOL moreToDo = YES;
NSLock *theLock = [[NSLock alloc] init];
...
while (moreToDo) {
    /* Do another increment of calculation */
    /* until there’s no more to do. */
    if ([theLock tryLock]) {
        /* Update display used by all threads. */
        [theLock unlock];
    }
}


我们可以使用指令 @synchronized 来简化 NSLock的使用,这样我们就不必显示编写创建NSLock,加锁并解锁相关代码。

- (void)myMethod:(id)anObj
{
    @synchronized(anObj)
    {
        // Everything between the braces is protected by the @synchronized directive.
    }
}

 
还有其他的一些锁对象,比如:循环锁NSRecursiveLock,条件锁NSConditionLock,分布式锁NSDistributedLock等等,在这里就不一一介绍了,大家去看官方文档吧。

用NSCodition同步执行的顺序

NSCodition 是一种特殊类型的锁,我们可以用它来同步操作执行的顺序。它与 mutex 的区别在于更加精准,等待某个 NSCondtion 的线程一直被 lock,直到其他线程给那个 condition 发送了信号。下面我们来看使用示例:

某个线程等待着事情去做,而有没有事情做是由其他线程通知它的。

[cocoaCondition lock];
while (timeToDoWork <= 0)
    [cocoaCondition wait];
 
timeToDoWork--; 
// Do real work here.
[cocoaCondition unlock];

其他线程发送信号通知上面的线程可以做事情了:

[cocoaCondition lock];
timeToDoWork++;
[cocoaCondition signal];
[cocoaCondition unlock];


线程间通信

线程在运行过程中,可能需要与其它线程进行通信。我们可以使用 NSObject 中的一些方法:
在应用程序主线程中做事情:

performSelectorOnMainThread:withObject:waitUntilDone:
performSelectorOnMainThread:withObject:waitUntilDone:modes:


在指定线程中做事情:

performSelector:onThread:withObject:waitUntilDone:
performSelector:onThread:withObject:waitUntilDone:modes:


在当前线程中做事情:

performSelector:withObject:afterDelay:
performSelector:withObject:afterDelay:inModes:


取消发送给当前线程的某个消息

cancelPreviousPerformRequestsWithTarget:
cancelPreviousPerformRequestsWithTarget:selector:object:


如在我们在某个线程中下载数据,下载完成之后要通知主线程中更新界面等等,可以使用如下接口:

- (void)myThreadMainMethod
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    // to do something in your thread job
    ...
    [self performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:NO];
    [pool release];
}

 

RunLoop

说到 NSThread 就不能不说起与之关系相当紧密的 NSRunLoop。Run loop 相当于 win32 里面的消息循环机制,它可以让你根据事件/消息(鼠标消息,键盘消息,计时器消息等)来调度线程是忙碌还是闲置。
系统会自动为应用程序的主线程生成一个与之对应的 run loop 来处理其消息循环。在触摸 UIView 时之所以能够激发 touchesBegan/touchesMoved 等等函数被调用,就是因为应用程序的主线程在 UIApplicationMain 里面有这样一个 run loop 在分发 input 或 timer 事件。

参考资料:

NSRunLoop概述和原理:http://xubenyang.me/384

官方文档:http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Multithreading/



    
最新技术文章:
▪Android开发之登录验证实例教程
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android提高之MediaPlayer播放网络视频的实现方法... iis7站长之家
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3