【学习笔记】多线程

网络上关于多线程的原理和用法的解释,随便一搜一大堆,但是那个宽泛过于学术性的解释,我看着太费力了。

我就用自己比较容易理解的白话来记录一下我学到的知识吧。

一、进程

  在移动端,一个app就是一个进程,在内存中占用一定的空间。

  在计算机里,一个程序就是一个进程,同样也占用内存空间。

  iOS同一时间点只有一个进程在使用CPU,只是系统把这个时间片分割地非常短,造成一种多个进程同时在执行的假象。

二、线程

  一个进程的执行,必然从一个主线程开始。

  整个应用可以由单个主线程运行,但是涉及到一些耗时的任务,例如打开淘宝app,必然要加载一大堆的图片。

  这时,如果只有单线程执行,程序必须等着图片都加载完毕才能继续往下执行,期间用户的交互就不起作用,这样用户体验很不好。

  所以,这时就衍生出多线程的概念,可以开子线程给那些耗时的任务,在旁边默默地执行,而不影响应用的大局。

  主线程,一般用来处理主体的展示(例如控制器的切换)和交互事件。

  子线程,一般用来处理耗时的任务。

  当然,并不是线程越多越好,多线程的使用也是要慎重考虑。

三、同步和异步

  我之前一直对同步和异步这个概念理解不清,常常混淆。同步是线程安全呢,还是异步线程安全呢?

  今天终于记清楚了这个概念,只要记住一句话——同步,就是同类;异步,就是异类。

  已经是同类,那肯定是处于同一个线程;异类,那就说明不是一个线程。

四、并行和串行

  并行:并发执行

  串行:按顺序执行,一个接一个

五、三种常用创建多线程方式

  1、NSThread:程序员手动管理线程,而多线程的情况下,线程什么时候执行完毕是未知的,如果管理不好,会造成内存泄露,所以这种方法不提倡。

  2 、NSOperation\NSOperationQueue。这两个类必须是搭配使用的,将操作放入操作队列中,依次执行。

  1>使用步骤:

  * 创建NSOperation

  * 添加NSOperation到NSOperationQueue

  2>优点:

  * 更加面向对象

  * 可以控制最大并发数 maxConcurrentOperationCount,使用这个属性可以保证同一时间内最大的并发数

  * 添加任务(Operation)之间的依赖 addDependency,使用这个属性可以控制一个Operation必须在其依赖的Operation执行完毕后才调用

//1.首先声明一个全局变量
NSOperationQueue *_queue;

//2.定义变量
_queue = [[NSOperationQueue alloc] init];
// 控制最大并发数:2
_queue.maxConcurrentOperationCount = 2;

//3.具体某个方法开启多线程
NSOperation *op = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"下载图片-%@", [NSThread currentThread]);
}];

NSOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"滤镜处理-%@", [NSThread currentThread]);
}];

// op1依赖于op(op执行完,才能执行op1)
[op1 addDependency:op];

//操作加入队列
[_queue addOperation:op];
[_queue addOperation:op1];

  

  3、GCD(官方推荐使用,纯C语言)

  调用同步(异步)执行的方法传入要并行(串行)执行的队列参数,执行方法内的block代码。

  说白了就是同一时间有一个还是多个线程执行,就看调用的方法和传入的队列类型。

  1> 队列类型

   * 全局队列

    * 所有添加到全局队列中的任务都是并发执行(同时执行,可能会开启多个线程)

    * dispatch_get_global_queue

  * 串行队列

    * 所有添加到串行队列中的任务都是按顺序执行(开一条线程)

    * dispatch_queue_create("myqueue", 0);

  * 主队列

    * 所有添加到主队列中的任务都是在主线程中执行的(跟方法名没有关系)

    * dispatch_get_main_queue

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

    * 同步:dispatch_sync,在当前线程执行任务,不会开启新的线程

    * 异步:dispatch_async,在其他线程执行任务,会开启新的线程

  3>代码demo演示:

  从组合学上说,总是共有四种情况:串行-同步、串行-异步、并行-同步、并行-异步。

  串行-同步:显然一直只有一个线程在执行(这个就是真正意义上单线程)

  串行-异步:可能会产生多个线程,但是同一时间只有一个线程在执行(异步虽然会产生多个不同线程,但是同一时间只有一个线程在执行)

  并行-同步:同一时间点有多个相同的线程在执行

  并行-异步:同一时间有多个不同的线程在执行(这是真正意义上的多线程)

  下面就只举两个例子,剩下的2种情况举一反三就是了

//串行队列,执行同步方法。说明只有一个线程在执行
dispatch_queue_t queue = dispatch_queue_create("myqueue", 0);
dispatch_sync(queue, ^{ // 耗时操作
    NSLog(@"dispatch_async-%@", [NSThread currentThread]);
});
//并行队列,异步执行。说明同一时间多个线程一起执行
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_sync(queue, ^{ // 耗时操作
    NSLog(@"dispatch_async-%@", [NSThread currentThread]);
});

  

  而主队列的使用,常常用来执行完子线程后,要讲数据返回主线程来进行处理。

  比如开启子线程下载某个资源,下载完毕需要回调到主线程来展示。

  可以在子线程完成的时候调用以下的方法返回主线程,同时能够将子线程得到的参数传给处理的selector方法里执行。

  [xxx performSelectorOnMainThread:@selector(xxx:) withObject:xxx waitUntilDone:YES]

  4、开启后台线程

 [self performSelectorInBackground:@selector(test) withObject:nil]

  

六、总结

  多线程是很重要的点,这些只是我目前掌握的理解,可能有很多不足和理解偏差,以后慢慢改进,继续补充。 

 

时间: 2024-10-18 05:44:59

【学习笔记】多线程的相关文章

IOS学习笔记 -- 多线程

多线程1.多线程的原理 1>.同一时间,CPU只能处理1条线程,只有1条线程在工作(执行) 2>.多线程并发(同时)执行,其实是CPU快速地在多条线程之间调度(切换) 3>.如果CPU调度线程的时间足够快,就造成了多线程并发执行的假象如果线程非常非常多,会发生: 1>.CPU会在N多线程之间调度,CPU会累死,消耗大量的CPU资源 2>.每条线程被调度执行的频次会降低(线程的执行效率降低) 2.多线程的优缺点 1>.多线程的优点 能适当提高程序的执行效率 能适当提高资源

Linux程序设计学习笔记----多线程编程线程同步机制之互斥量(锁)与读写锁

互斥锁通信机制 基本原理 互斥锁以排他方式防止共享数据被并发访问,互斥锁是一个二元变量,状态为开(0)和关(1),将某个共享资源与某个互斥锁逻辑上绑定之后,对该资源的访问操作如下: (1)在访问该资源之前需要首先申请互斥锁,如果锁处于开状态,则申请得到锁并立即上锁(关),防止其他进程访问资源,如果锁处于关,则默认阻塞等待. (2)只有锁定该互斥锁的进程才能释放该互斥锁. 互斥量类型声明为pthread_mutex_t数据类型,在<bits/pthreadtypes.h>中有具体的定义. 互斥量

Linux程序设计学习笔记----多线程编程之线程同步之条件变量

转载请注明出处:http://blog.csdn.net/suool/article/details/38582521. 基本概念与原理 互斥锁能够解决资源的互斥访问,但是在某些情况下,互斥并不能解决问题,比如两个线程需 要互斥的处理各自的操作,但是一个线程的操作仅仅存在一种条件成立的情况下执行,一旦错过不可再重现,由于线程间相互争夺cpu资源,因此在条件成立的时候,该线程不一定争夺到cpu而错过,导致永远得不到执行..... 因此需要某个机制来解决此问题,更重要的是,线程仅仅只有一种情况需要执

JAVA学习笔记 -- 多线程之共享资源

在多线程程序运行过程中,可能会涉及到两个或者多个线程试图同时访问同一个资源.为了防止这种情况的发生,必须在线程使用共享资源时给资源"上锁",以阻挡其它线程的访问.而这种机制也常常被称为互斥量,本文主要介绍它的两种方式synchronized和Lock . 1.synchronized 当任务要执行被synchronized关键字保护的代码片段的时候,它会检查锁是否可用,然后获取锁,执行代码,释放锁.synchronized也有两种用法: A.synchronized方法 import

Linux程序设计学习笔记----多线程编程基础概念与基本操作

转载请注明出处,http://blog.csdn.net/suool/article/details/38542543,谢谢. 基本概念 线程和进程的对比 用户空间资源对比 每个进程在创建的时候都申请了新的内存空间以存储代码段\数据段\BSS段\堆\栈空间,并且这些的空间的初始化值是父进程空间的,父子进程在创建后不能互访资源. 而每个新创建的线程则仅仅申请了自己的栈,空间,与同进程的其他线程共享该进程的其他数据空间包括代码段\数据段\BSS段\堆以及打开的库,mmap映射的文件与共享的空间,使得

java学习笔记 多线程

进程是程序的一次动态执行过程,需要经历代码加载,代码执行,执行完毕的一个完整过程. 多进程操作系统能同时运行多个进程(程序),由于cpu具有备份时机制,所以每个进程都能循环获得自己的cpu时间片.由于cpu执行速度非常快,使得所有程序好像是在"同时运行"一样. 线程是比进程更小的单位,线程是在进程基础上进一步的划分.多线程是指一个进程在执行过程中可以产生多个更小的程序单元,这些更小的程序单元称之为线程.(java在运行中至少会启动两个线程:1,main线程 2,垃圾回收线程) 线程的实

04-java学习笔记-多线程1

1.多线程概述 进程:是一个正在执行中的程序. 每一个进程都有一个执行单元.该顺序是一个执行路径,或者叫一个控制单元. 线程:就是进程中的一个独立的控制单元. 线程在控制着进程的执行. 一个进程中至少有一个线程. Java VM  启动的时候会有一个进程 java.exe 该进程中至少一个线程负责java程序的执行. 而且这个线程运行的代码存在于main方法中. 该线程称之为主线程. 扩展:其实更细节说明jvm, jvm启动不止一个线程,还有负责垃圾回收机制的线程. 2.创建线程-继承Threa

Java学习笔记---多线程同步的五种方法

一.引言 前几天面试,被大师虐残了,好多基础知识必须得重新拿起来啊.闲话不多说,进入正题. 二.为什么要线程同步 因为当我们有多个线程要同时访问一个变量或对象时,如果这些线程中既有读又有写操作时,就会导致变量值或对象的状态出现混乱,从而导致程序异常.举个例子,如果一个银行账户同时被两个线程操作,一个取100块,一个存钱100块.假设账户原本有0块,如果取钱线程和存钱线程同时发生,会出现什么结果呢?取钱不成功,账户余额是100.取钱成功了,账户余额是0.那到底是哪个呢?很难说清楚.因此多线程同步就

Java学习笔记—多线程(java.util.concurrent并发包概括,转载)

一.描述线程的类:Runable和Thread都属于java.lang包 二.内置锁synchronized属于jvm关键字,内置条件队列操作接口Object.wait()/notify()/notifyAll()属于java.lang包 二.提供内存可见性和防止指令重排的volatile属于jvm关键字 四.而java.util.concurrent包(J.U.C)中包含的是java并发编程中有用的一些工具类,包括几个部分: 1.locks部分:包含在java.util.concurrent.

Java学习笔记—多线程(并发工具类,java.util.concurrent.atomic包)

在JDK的并发包里提供了几个非常有用的并发工具类.CountDownLatch.CyclicBarrier和Semaphore工具类提供了一种并发流程控制的手段,Exchanger工具类则提供了在线程间交换数据的一种手段.本章会配合一些应用场景来介绍如何使用这些工具类. CountDownLatch CountDownLatch允许一个或多个线程等待其他线程完成操作.假如有这样一个需求:我们需要解析一个Excel里多个sheet的数据,此时可以考虑使用多线程,每个线程解析一个sheet里的数据,