转 多线程补充

进程和线程

要使用多线程,首先需要理解进程和线程这2个概念。这里我简单的说一下。

所谓进程对应的是一个应用程序,负责开辟内存空间供应用程序使用,但是进程不能执行任务(指令)。一个进程至少包含一条线程,线程是程序的执行流。

•iOS程序启动时,在创建一个进程的同时, 会开始运行一个线程,该线程被称为主线程

系统中的每一个进程都有自己独立的虚拟内存空间,而同一个进程中的多个线程则共用进程的内存空间

•每创建一个新的线程,都会消耗一定内存和CPU时间

•当多个线程对同一个资源出现争夺的时候需要注意线程安全问题

多线程的应用及使用注意事项

将耗时、轮询或者并发需求高等任务分配到其他线程执行,并由主线程负责统一更新界面会使得应用程序更加流畅,用户体验更好,例如网络请求,播放游戏的背景音乐等。

•线程使用不是无节制的

–iOS中的主线程的堆栈大小是1M

–从第二个线程开始都是512KB

–这些数值不能通过编译器开关或线程API函数更改

注:更新UI界面,处理界面和用户之间的交互事件一定要在主线程中处理。

iOS中的多线程技术

1.NSObject的多线程方法-对NSThread的封装(一个NSThread对象对应一条线程)

•开启后台线程执行任务的方法

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

•在后台线程中通知主线程执行任务的方法

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

•获取线程信息

[NSThread currentThread];

•线程休眠

[NSThread sleepForTimeInterval:1.0f];

提示:

–performSelectorInBackground方法本身是在主线程中执行的,而选择器指定的方法是在后台线程中进行的

–尽管使用performSelectorInBackground方法调用的任务可以更新UI界面,但是在实际开发中,涉及到UI界面的更新操作,还是要使用performSelectorOnMainThread方法,以避免不必要的麻烦

注:

•内存管理对于多线程非常重要

•Objective-C可以凭借@autoreleasepool使用内存资源,并需要时回收资源

•每个线程都需要有@autoreleasepool,否则可能会出现内存泄漏

2.NSThread

•创建线程方法:

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

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

•参数说明:

–selector:线程执行的方法,只能有一个参数,不能有返回值

–target:selector消息发送的对象

–argument:传输给target的唯一参数,也可以是nil

3.NSOperation/NSOperationQueue

•NSOperation的两个子类

1.NSInvocationOperation

2.NSBlockOperation

•工作原理:

1.用NSOperation封装要执行的操作

2.将创建好的NSOperation对象放NSOperationQueue中

3.启动OperationQueue开始新的线程执行队列中的操作

•注意事项:

1.使用多线程时通常需要控制线程的并发数,因为线程会消耗系统资源,同时运行的线程过多,系统会变慢

2.使用以下方法可以控制并发的线程数量:

-(void)setMaxConcurrentOperationCount:(NSInteger)cnt;

3.使用addDependency可以建立操作之间的依赖关系,设定操作的执行顺序

上面的程序设置依赖关系后,只有等操作a和b都执行完,才会执行c.

4.GCD

•GCD队列:

1.全局队列:所有添加到主队列中的任务都是并发执行的(可能会开启多条线程)

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

2.串行队列:所有添加到串行队列中的任务都是顺序执行的(只可能会开启一条线程)

dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);

3.主队列:所有添加到主队列中的任务都是在主线程中执行的

dispatch_get_main_queue();

•异步操作

–dispatch_async 在其他线程执行任务,会开启新的线程

–异步方法无法确定任务的执行顺序

•同步操作

–dispatch_sync 在当前在线程执行任务,不开启新的线程

–同步操作与队列无关

–同步方法会依次执行,能够决定任务的执行顺序

–更新界面UI时,最好使用同步方法

注:同步还是异步,取决于方法名(不影响主队列,影响全局队列、串行队列)。

时间: 2024-12-08 13:29:26

转 多线程补充的相关文章

多线程补充以及协程

多线程补充以及协程 1.线程队列 线程队列用法与进程队列一样 import queue #先进先出 q = queue.Queue() q.put(1) q.put(2) q.put(3) print(q.get()) # 1 print(q.get()) # 2 print(q.get()) # 3 print(q.get(block=False)) # 取不到值直接报错 q.get(timeout=2) # 阻塞2秒,还没有值直接报错 import queue # 后进先出 LiFo 堆栈

多线程补充---day02

01-使用create函数创建的并发队列和全局并发队列的主要区别: 1.全局并发队列在整个应用程序中本身是默认存在的,并且对应的有高优先级,低优先级,默认优先级,后台优先级共四个并发队列. 2.使用栅函数时候,苹果官方规定栅栏函数只有在和使用creste函数一起使用才有效. 02-xcode 7.0版本之后.http请求问题修改info.plist的NSAppTransportSecurity修改为字典类型,添加NSAllowArbitraryLoadskey修改为YES. ##########

JavaSE:多线程补充--线程通信

线程通信我认为是多线程中最难掌握的部分了,这里通过两个例子来说明一下. 第一个: 使用两个线程打印 1-100. 线程1, 线程2 交替打印 public class Print implements Runnable{ int i = 1; public void run(){ while(true){ synchronized(this){ if(i<100){ notify(); System.out.println(Thread.currentThread().getName() + &qu

多线程补充内容——Java面向对象基础(28)

一.一个经典的问题——生产者,消费者问题 1.需要明确的是,只有当生产者生产出产品后,消费者才能消费. 2.只有当消费者消费了产品后,生产者才能再生产. 3.即产品为资源 4.采用信号灯的机制处理,产品设为引号灯. /** * 生产者与消费者关系: * 信号灯:T F * 当信号灯T: 生产者生产,生产完消费者再消费. * 当信号灯F: 消费者消费,消费完生产者再生产. * * */ public class Product { private String productName; priva

多进程(补充),多线程,锁

多进程补充joinable Queue q=JoinableQueueq.put(1)q.put(2)print(q.get())q.task_done() 告诉容器已经处理完成了一个数据 有几个数据就要调用几次q.task_done() q.join() 也是一个阻塞函数 一直到队列中的数据被处理完毕(task_done的调用次数等于队列中的数据数量)print('处理完成') # from multiprocessing import Process,Queue,JoinableQueue

8-2高级基础总结 多线程,网络编程,Java基础补充

一个程序在运行的过程中就产生一个进程,一个进程有可能会使用到一个到多个线程,而Java中经常会使用到多线程,比如debug.每一次调用方法都会使用到多线程.Java中可以用Thread 的子类来创建一个线程,然后子类里面的run方法来执行我们所要编程的代码.也可以直接在匿名子类中创建并override run方法. synchronized同步锁机制.一个对象只有一把锁,同一时刻只能一个线程持有这把锁. 非静态同步方法申请的锁是类的当前对象的锁,静态同步方法申请的锁是类的Class对象的锁.同步

补充---spring多线程任务调度

在spring任务调度的基础上增加多线程 三种方式: (1)使用OpenSymphony Quartz 调度器 (2)使用JDK Timer支持类 (3)SpringTaskExecutor抽象 spring 容器配置 <!-- 接收数据 --> <!-- 异步线程池 --> <bean id="threadPool" class="org.springframework.scheduling.concurrent.ThreadPoolTaskE

JAVA多线程及补充

进程 运行中的应用程序叫进程,每个进程运行时,都有自已的地址空间(内存空间)如IE浏览器在任务管器中可以看到操作系统都是支持多进程的 线程 线程是轻量级的进程,是进程中一个负责程序执行的控制单元线程没有独立的地址空间(内存空间)线程是由进程创建的(寄生在进程中)一个进程可以拥有多个线程,至少一个线程线程有几种状态(新建new,就绪Runnable,运行Running,阻塞Blocked,死亡Dead)开启多个线程是为了同时运行多部分代码,每个线程都有自已的运行的内容,这个内容可以称线程要执行的任

libcurl 多线程使用注意事项(补充)——HTTPS,openssl多线程使用加锁

问题 多线程libcurl运行一段时间后出现崩掉,没有确定的点,没有确定的URL.一直查看源代码没有问题,最后通过debug跟踪发现是在访问SSL的时候出现的crash. 才想起来openssl是不支持多线程的,要自己做加锁处理.而且libcurl中并没有支持相关的加锁操作. 解决办法: 在初始化libcurl的时候为openssl创建一个互斥锁函数,一个回调函数传给openss openssl锁l函数原形 :void (* func )(int ,int , const char * ,int