一、什么是NSThread

NSThread是基于线程使用,轻量级的多线程编程方法(相对GCD和NSOperation),一个NSThread对象代表一个线程,

需要手动管理线程的生命周期,处理线程同步等问题。

二、NSThread方法介绍

1)动态创建

1
NSThread * newThread = [[NSThread alloc]initWithTarget:self


selector:@selector(threadRun) object:nil];

动态方法返回一个新的thread对象,需要调用start方法来启动线程

2)静态创建

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

由于静态方法没有返回值,如果需要获取新创建的thread,需要在selector中调用获取当前线程的方法

3)线程开启

1
[newThread start];

4)线程暂停

1
2
[NSThread sleepForTimeInterval:1.0]; (以暂停一秒为例)
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];

NSThread的暂停会有阻塞当前线程的效果

5)线程取消

1
[newThread cancel];

取消线程并不会马上停止并退出线程,仅仅只作(线程是否需要退出)状态记录

6)线程停止

1
[NSThread exit];

停止方法会立即终止除主线程以外所有线程(无论是否在执行任务)并退出,需要在掌控所有线程状态的情况下调用此方法,

否则可能会导致内存问题。

7)获取当前线程

1
[NSThread currentThread];

8)获取主线程

1
[NSThread mainThread];

9)线程优先级设置

iOS 8以前使用

1
[NSThread setThreadPriority:1.0];

这个方法的优先级的数值设置让人困惑,因为你不知道你应该设置多大的值是比较合适的,因此在iOS8之后,threadPriority添加了

一句注释:To be deprecated; use qualityOfService below

意思就是iOS 8以后推荐使用qualityOfService属性,通过量化的优先级枚举值来设置

qualityOfService的枚举值如下:

  • NSQualityOfServiceUserInteractive:最高优先级,用于用户交互事件

  • NSQualityOfServiceUserInitiated:次高优先级,用于用户需要马上执行的事件

  • NSQualityOfServiceDefault:默认优先级,主线程和没有设置优先级的线程都默认为这个优先级

  • NSQualityOfServiceUtility:普通优先级,用于普通任务

  • NSQualityOfServiceBackground:最低优先级,用于不重要的任务

比如给线程设置次高优先级:

1
[newThread setQualityOfService:NSQualityOfServiceUserInitiated];

三、线程间通信

常用的有三种:

1、指定当前线程执行操作

1
2
3
[self performSelector:@selector(threadRun)];
[self performSelector:@selector(threadRun) withObject:nil];
[self performSelector:@selector(threadRun) withObject:nil afterDelay:2.0];

2、(在其他线程中)指定主线程执行操作

1
[self performSelectorOnMainThread:@selector(threadRun) withObject:nil


waitUntilDone:YES];

注意:更新UI要在主线程中进行

3、(在主线程中)指定其他线程执行操作

1
2
[self performSelector:@selector(threadRun) onThread:newThread


withObject:nil waitUntilDone:YES];

//这里指定为某个线程
[self performSelectorInBackground:@selector(threadRun) withObject:nil];

//这里指定为后台线程

四、线程同步

线程和其他线程可能会共享一些资源,当多个线程同时读写同一份共享资源的时候,可能会引起冲突。线程同步是指是指在一定的时间内只允许

某一个线程访问某个资源

iOS实现线程加锁有NSLock和@synchronized两种方式。

五、线程的创建和使用实例:模拟售票

情景:某演唱会门票发售,在广州和北京均开设窗口进行销售,以下是代码实现

先监听线程退出的通知,以便知道线程什么时候退出

1
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(threadExitNotice)

name:NSThreadWillExitNotification object:nil];

设置演唱会的门票数量

1
_ticketCount = 50;

新建两个子线程(代表两个窗口同时销售门票)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
NSThread * window1 = [[NSThread alloc]initWithTarget:self


selector:@selector(saleTicket) object:nil];
window1.name = @"北京售票窗口";
[window1 start];
NSThread * window2 = [[NSThread alloc]initWithTarget:self


selector:@selector(saleTicket) object:nil];
window2.name = @"广州售票窗口";
[window2 start];
线程启动后,执行saleTicket,执行完毕后就会退出,为了模拟持续售票的过程,

我们需要给它加一个循环
- (void)saleTicket {
    while (1) {
    //如果还有票,继续售卖
        if (_ticketCount > 0) {
        _ticketCount --;
        NSLog(@"%@", [NSString stringWithFormat:@"剩余票数:%ld 窗口:%@", _ticketCount, [NSThread currentThread].name]);
        [NSThread sleepForTimeInterval:0.2];
    }
    //如果已卖完,关闭售票窗口
    else {
        break;
    }
}
}

执行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2016-04-06 19:25:36.637 MutiThread[4705:1371666] 剩余票数:9 窗口:广州售票窗口
2016-04-06 19:25:36.637 MutiThread[4705:1371665] 剩余票数:8 窗口:北京售票窗口
2016-04-06 19:25:36.839 MutiThread[4705:1371666] 剩余票数:7 窗口:广州售票窗口
2016-04-06 19:25:36.839 MutiThread[4705:1371665] 剩余票数:7 窗口:北京售票窗口
2016-04-06 19:25:37.045 MutiThread[4705:1371666] 剩余票数:5 窗口:广州售票窗口
2016-04-06 19:25:37.045 MutiThread[4705:1371665] 剩余票数:6 窗口:北京售票窗口
2016-04-06 19:25:37.250 MutiThread[4705:1371665] 剩余票数:4 窗口:北京售票窗口
2016-04-06 19:25:37.250 MutiThread[4705:1371666] 剩余票数:4 窗口:广州售票窗口
2016-04-06 19:25:37.456 MutiThread[4705:1371666] 剩余票数:2 窗口:广州售票窗口
2016-04-06 19:25:37.456 MutiThread[4705:1371665] 剩余票数:3 窗口:北京售票窗口
2016-04-06 19:25:37.661 MutiThread[4705:1371665] 剩余票数:1 窗口:北京售票窗口
2016-04-06 19:25:37.661 MutiThread[4705:1371666] 剩余票数:1 窗口:广州售票窗口
2016-04-06 19:25:37.866 MutiThread[4705:1371665] 剩余票数:0 窗口:北京售票窗口
2016-04-06 19:25:37.867 MutiThread[4705:1371666] <nsthread: 0x7fdc91e289f0>

{number = 3, name = 广州售票窗口} Will Exit
2016-04-06 19:25:38.070 MutiThread[4705:1371665] <nsthread: 0x7fdc91e24d60>

{number = 2, name = 北京售票窗口} Will Exit</nsthread: 0x7fdc91e24d60>

</nsthread: 0x7fdc91e289f0>

可以看到,票的销售过程中出现了剩余数量错乱的情况,这就是前面提到的线程同步问题。

售票是一个典型的需要线程同步的场景,由于售票渠道有很多,而票的资源是有限的,当多个渠道在短时间内卖出大量

的票的时候,如果没有同步机制来管理票的数量,将会导致票的总数和售出票数对应不上的错误。

我们在售票的过程中给票加上同步锁:同一时间内,只有一个线程能对票的数量进行操作,当操作完成之后,其他线程

才能继续对票的数量进行操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- (void)saleTicket {
    while (1) {
    @synchronized(self) {
        //如果还有票,继续售卖
        if (_ticketCount > 0) {
        _ticketCount --;
        NSLog(@"%@", [NSString stringWithFormat:@"剩余票数:%ld 窗口:%@", _ticketCount, [NSThread currentThread].name]);
        [NSThread sleepForTimeInterval:0.2];
        }
        //如果已卖完,关闭售票窗口
        else {
                break;
            }
        }
    }
}

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
2016-04-06 19:31:27.913 MutiThread[4718:1406865] 剩余票数:11 窗口:北京售票窗口
2016-04-06 19:31:28.115 MutiThread[4718:1406866] 剩余票数:10 窗口:广州售票窗口
2016-04-06 19:31:28.317 MutiThread[4718:1406865] 剩余票数:9 窗口:北京售票窗口
2016-04-06 19:31:28.522 MutiThread[4718:1406866] 剩余票数:8 窗口:广州售票窗口
2016-04-06 19:31:28.728 MutiThread[4718:1406865] 剩余票数:7 窗口:北京售票窗口
2016-04-06 19:31:28.929 MutiThread[4718:1406866] 剩余票数:6 窗口:广州售票窗口
2016-04-06 19:31:29.134 MutiThread[4718:1406865] 剩余票数:5 窗口:北京售票窗口
2016-04-06 19:31:29.339 MutiThread[4718:1406866] 剩余票数:4 窗口:广州售票窗口
2016-04-06 19:31:29.545 MutiThread[4718:1406865] 剩余票数:3 窗口:北京售票窗口
2016-04-06 19:31:29.751 MutiThread[4718:1406866] 剩余票数:2 窗口:广州售票窗口
2016-04-06 19:31:29.952 MutiThread[4718:1406865] 剩余票数:1 窗口:北京售票窗口
2016-04-06 19:31:30.158 MutiThread[4718:1406866] 剩余票数:0 窗口:广州售票窗口
2016-04-06 19:31:30.363 MutiThread[4718:1406866] <nsthread: 0x7ff0c1637320>

{number = 3, name = 广州售票窗口} Will Exit
2016-04-06 19:31:30.363 MutiThread[4718:1406865] <nsthread: 0x7ff0c1420cb0>

{number = 2, name = 北京售票窗口} Will Exit</nsthread: 0x7ff0c1420cb0>

</nsthread: 0x7ff0c1637320>

可以看到,票的数量没有出现错乱的情况。

线程的持续运行和退出

我们注意到,线程启动后,执行saleTicket完毕后就马上退出了,怎样能让线程一直运行呢(窗口一直开放,

可以随时指派其卖演唱会的门票的任务),答案就是给线程加上runLoop

1
2

//先监听线程退出的通知,以便知道线程什么时候退出
[[NSNotificationCenter defaultCenter]addObserver:self


selector:@selector(threadExitNotice)

name:NSThreadWillExitNotification object:nil];
1
2
//设置演唱会的门票数量
_ticketCount = 50;

新建两个子线程(代表两个窗口同时销售门票)

1
2
3
4
NSThread * window1 = [[NSThread alloc]initWithTarget:self


selector:@selector(thread1) object:nil];
[window1 start];
NSThread * window2 = [[NSThread alloc]initWithTarget:self


selector:@selector(thread2) object:nil];
[window2 start];

接着我们给线程创建一个runLoop

1
2
3
4
5
6
7
8
9
10
- (void)thread1 {
    [NSThread currentThread].name = @"北京售票窗口";
    NSRunLoop * runLoop1 = [NSRunLoop currentRunLoop];
    [runLoop1 runUntilDate:[NSDate date]]; //一直运行
}
- (void)thread2 {
    [NSThread currentThread].name = @"广州售票窗口";
    NSRunLoop * runLoop2 = [NSRunLoop currentRunLoop];
    [runLoop2 runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:10.0]]; //自定义运行时间
}

然后就可以指派任务给线程了,这里我们让两个线程都执行相同的任务(售票)

1
2
[self performSelector:@selector(saleTicket) onThread:window1


withObject:nil waitUntilDone:NO];
[self performSelector:@selector(saleTicket) onThread:window2


withObject:nil waitUntilDone:NO];

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
2016-04-06 19:43:22.585 MutiThread[4762:1478200] 剩余票数:11 窗口:北京售票窗口
2016-04-06 19:43:22.788 MutiThread[4762:1478201] 剩余票数:10 窗口:广州售票窗口
2016-04-06 19:43:22.993 MutiThread[4762:1478200] 剩余票数:9 窗口:北京售票窗口
2016-04-06 19:43:23.198 MutiThread[4762:1478201] 剩余票数:8 窗口:广州售票窗口
2016-04-06 19:43:23.404 MutiThread[4762:1478200] 剩余票数:7 窗口:北京售票窗口
2016-04-06 19:43:23.609 MutiThread[4762:1478201] 剩余票数:6 窗口:广州售票窗口
2016-04-06 19:43:23.810 MutiThread[4762:1478200] 剩余票数:5 窗口:北京售票窗口
2016-04-06 19:43:24.011 MutiThread[4762:1478201] 剩余票数:4 窗口:广州售票窗口
2016-04-06 19:43:24.216 MutiThread[4762:1478200] 剩余票数:3 窗口:北京售票窗口
2016-04-06 19:43:24.422 MutiThread[4762:1478201] 剩余票数:2 窗口:广州售票窗口
2016-04-06 19:43:24.628 MutiThread[4762:1478200] 剩余票数:1 窗口:北京售票窗口
2016-04-06 19:43:24.833 MutiThread[4762:1478201] 剩余票数:0 窗口:广州售票窗口
2016-04-06 19:43:25.039 MutiThread[4762:1478201]


<nsthread: 0x7fe0d3c24360>{number = 3, name = 广州售票窗口}

Will Exit</nsthread: 0x7fe0d3c24360>

可以看到,当票卖完后,两个线程并没有退出,仍在继续运行,当到达指定时间后,线程2退出了,

如果需要让线程1退出,需要我们手动管理。

比如我们让线程完成任务(售票)后自行退出,可以这样操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
- (void)saleTicket {
    while (1) {
        @synchronized(self) {
        //如果还有票,继续售卖
        if (_ticketCount > 0) {
        _ticketCount --;
            NSLog(@"%@", [NSString stringWithFormat:@"剩余票数:%ld 窗口:%@", _ticketCount, [NSThread currentThread].name]);
            [NSThread sleepForTimeInterval:0.2];
        }
        //如果已卖完,关闭售票窗口
        else {
            if ([NSThread currentThread].isCancelled) {
            break;
        }else {
            NSLog(@"售卖完毕");
            //给当前线程标记为取消状态
            [[NSThread currentThread] cancel];
            //停止当前线程的runLoop
            CFRunLoopStop(CFRunLoopGetCurrent());
            }
        }
      }
    }
}

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2016-04-06 20:08:38.287 MutiThread[4927:1577193] 剩余票数:10 窗口:北京售票窗口
2016-04-06 20:08:38.489 MutiThread[4927:1577194] 剩余票数:9 窗口:广州售票窗口
2016-04-06 20:08:38.690 MutiThread[4927:1577193] 剩余票数:8 窗口:北京售票窗口
2016-04-06 20:08:38.892 MutiThread[4927:1577194] 剩余票数:7 窗口:广州售票窗口
2016-04-06 20:08:39.094 MutiThread[4927:1577193] 剩余票数:6 窗口:北京售票窗口
2016-04-06 20:08:39.294 MutiThread[4927:1577194] 剩余票数:5 窗口:广州售票窗口
2016-04-06 20:08:39.499 MutiThread[4927:1577193] 剩余票数:4 窗口:北京售票窗口
2016-04-06 20:08:39.700 MutiThread[4927:1577194] 剩余票数:3 窗口:广州售票窗口
2016-04-06 20:08:39.905 MutiThread[4927:1577193] 剩余票数:2 窗口:北京售票窗口
2016-04-06 20:08:40.106 MutiThread[4927:1577194] 剩余票数:1 窗口:广州售票窗口
2016-04-06 20:08:40.312 MutiThread[4927:1577193] 剩余票数:0 窗口:北京售票窗口
2016-04-06 20:08:40.516 MutiThread[4927:1577194] 售卖完毕
2016-04-06 20:08:40.516 MutiThread[4927:1577193] 售卖完毕
2016-04-06 20:08:40.517 MutiThread[4927:1577193]


<nsthread: 0x7fb719d54000>{number = 2, name = 北京售票窗口} Will Exit
2016-04-06 20:08:40.517 MutiThread[4927:1577194]


<nsthread: 0x7fb719d552f0>{number = 3, name = 广州售票窗口}

Will Exit</nsthread: 0x7fb719d552f0></nsthread: 0x7fb719d54000>

如果确定两个线程都是isCancelled状态,可以调用[NSThread exit]方法来终止线程。

NSThread

  • 一个NSThread对象就代表一条线程
  • NSThread会在执行完任务函数是被自动收回
  • 一些常用的函数
    //创建线程
    NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector() object:nil];
    //object存的是参数

    //修改参数名
    thread.name = @"我的多线程";

    //获取主线程
    NSThread *thread = [NSThread mainThread];

    //创建线程并自动启动
    [NSThread detachNewThreadSelector:@selector() toTarget:self withObject:nil];

    //隐士创建
    [self performSelectorInBackground:@selector() withObject:nil];

    //获取当前线程
    [NSThread currentThread]

    //启动线程
    - (void)start;

    //阻塞(暂停)线程
    + (void)sleepUntilDate:(NSDate *)date;
    + (void)sleepForTimeInterval:(NSTimeInterval)ti;
    // 进入阻塞状态

    //停止当前正在运行的进程
    + (void)exit;
    // 进入死亡状态,一旦死亡则不能重启

资源共享

  • 1块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源
  • 当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题

解决办法互斥锁

  • 互斥锁使用格式

    • @synchronized(锁对象) { // 需要锁定的代码 }
    • 只用一把锁,多锁是无效的
  • 互斥锁的优缺点

    • 优点:能有效防止因多线程抢夺资源造成的数据安全问题
    • 缺点:需要消耗大量的CPU资源
  • 互斥锁的使用前提:多条线程抢夺同一块资源

  • 互斥锁的示例代码
#import "ViewController.h"

@interface ViewController ()
/** 售票机1*/
@property (strong,nonatomic) NSThread *threadOne;
/** 售票机2*/
@property (strong,nonatomic) NSThread *threadTwo;
/** 售票机3*/
@property (strong,nonatomic) NSThread *threadThree;
/** 售票机4*/
@property (strong,nonatomic) NSThread *threadFour;
/** 售票机5*/
@property (strong,nonatomic) NSThread *threadFive;

/** 数量*/
@property (assign,nonatomic) NSInteger count;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    //创建线程
    self.threadOne = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"one"];
    self.threadTwo = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"two"];
    self.threadThree = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"three"];
    self.threadFour = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"four"];
    self.threadFive = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"five"];
    self.count = 100;
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //开始线程
    [self.threadOne start];
    [self.threadTwo start];
    [self.threadThree start];
    [self.threadFour start];
    [self.threadFive start];
}

- (void)run:(NSString *)param
{
    while (1) {
        //self是锁对象
        @synchronized(self)
        {

            if (self.count > 0) {
                _count--;
                NSLog(@"%zd-----%@",self.count,[NSThread currentThread]);
            }
            else
            {
                NSLog(@"卖完了----%@",[NSThread currentThread]);
                break;
            }
        }
    }
}
@end

iOS多线程篇:NSThread简单介绍和使用的更多相关文章

  1. iOS开发多线程篇—NSOperation简单介绍

    iOS开发多线程篇—NSOperation简单介绍 一.NSOperation简介 1.简单说明 NSOperation的作⽤:配合使用NSOperation和NSOperationQueue也能实现 ...

  2. 【iOS开发】NSOperation简单介绍

    iOS开发多线程篇—NSOperation简单介绍 一.NSOperation简介 1.简单说明 NSOperation的作⽤:配合使用NSOperation和NSOperationQueue也能实现 ...

  3. iOS开发数据库篇—FMDB简单介绍

    iOS开发数据库篇—FMDB简单介绍 一.简单说明 1.什么是FMDB FMDB是iOS平台的SQLite数据库框架 FMDB以OC的方式封装了SQLite的C语言API 2.FMDB的优点 使用起来 ...

  4. iOS开发UI篇—UITabBarController简单介绍

    iOS开发UI篇—UITabBarController简单介绍 一.简单介绍 UITabBarController和UINavigationController类似,UITabBarControlle ...

  5. iOS开发UI篇—Modal简单介绍

    iOS开发UI篇—Modal简单介绍 一.简单介绍 除了push之外,还有另外一种控制器的切换方式,那就是Modal 任何控制器都能通过Modal的形式展⽰出来 Modal的默认效果:新控制器从屏幕的 ...

  6. iOS开发数据库篇—SQLite简单介绍

    iOS开发数据库篇—SQLite简单介绍 一.离线缓存 在项目开发中,通常都需要对数据进行离线缓存的处理,如新闻数据的离线缓存等. 说明:离线缓存一般都是把数据保存到项目的沙盒中.有以下几种方式 (1 ...

  7. iOS开发UI篇—Kvc简单介绍

    ios开发UI篇—Kvc简单介绍 一.KVC简单介绍 KVC key valued coding 键值编码 KVC通过键值间接编码 补充: 与KVC相对的时KVO,即key valued observ ...

  8. iOS开发UI篇—UIWindow简单介绍

    iOS开发UI篇—UIWindow简单介绍 一.简单介绍 UIWindow是一种特殊的UIView,通常在一个app中只会有一个UIWindow iOS程序启动完毕后,创建的第一个视图控件就是UIWi ...

  9. iOS开发UI篇—Quartz2D简单介绍

    iOS开发UI篇—Quartz2D简单介绍 一.什么是Quartz2D Quartz 2D是⼀个二维绘图引擎,同时支持iOS和Mac系统 Quartz 2D能完成的工作: 绘制图形 : 线条\三角形\ ...

  10. iOS开发拓展篇—UIDynamic(简单介绍)

    iOS开发拓展篇—UIDynamic(简单介绍) 一.简单介绍 1.什么是UIDynamic UIDynamic是从iOS 7开始引入的一种新技术,隶属于UIKit框架 可以认为是一种物理引擎,能模拟 ...

随机推荐

  1. ROS_Kinetic_x 目前已更新的常用機器人資料 rosbridge agvs pioneer_teleop nao TurtleBot

    Running Rosbridge Description: This tutorial shows you how to launch a rosbridge server and talk to ...

  2. linux中Cron定时任务系统命令详解

    分类:Linux VPS教程 作者:阿川 发布时间:October 13, 2011 有很多同学在购买VPS之后,需要用到计划任务.但是又对计划任务不太了解,所以.今天我们的帮助中心主要是给大家提供一 ...

  3. Description Resource Path Location Type AndroidManifest.xml file missing!

    这个问题又找了好久.国内回答的确不敢恭维. 本回答来自谷歌:   This is build issue. Go to Menu in eclipse, Project>clean then P ...

  4. 使用Swift开发一个MacOS的菜单状态栏App

    猴子原创,欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/52054107 ...

  5. Java虚拟机定义

    虚拟机是一种抽象化的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的.Java虚拟机有自己完善的硬体架构,如处理器.堆栈.寄存器等,还具有相应的指令系统.JVM屏蔽了与具体操作系统平台相关的 ...

  6. Hessian源码分析--HessianServlet

    Hessian可以通过Servlet来对外暴露服务,HessianServlet继承于HttpServlet,但这仅仅是一个外壳,使用web服务器来提供对外的Http请求,在web.xml中我们会进行 ...

  7. Mybatis源码之Statement处理器CallableStatementHandler(六)

    CallableStatementHandler实际就是使用CallableStatement来执行SQL语句,当然它执行的是存储过程. 源码如下: /** * @author Clinton Beg ...

  8. Install and run DB Query Analyzer 6.04 on Microsoft Windows 10

          Install and run DB Query Analyzer 6.04 on Microsoft Windows 10  DB Query Analyzer is presented ...

  9. 高通msm8994启动流程简介

    处理器信息 8994包含如下子系统: 子系统 处理器 含义 APSS 4*Cortex-A53 应用子系统 APSS 4*Cortex-A57 应用子系统 LPASS QDSP6 v5.5A(Hexa ...

  10. 理解WebKit和Chromium: 硬件加速之RenderLayer树到合成树

    转载请注明原文地址:http://blog.csdn.net/milado_nju ## 概述 在前面的章节中,笔者介绍了WebKit渲染引擎是如何有HTML网页构建DOM树.RenderObject ...