https://www.jianshu.com/p/072111f5889d

2017.03.05 22:54* 字数 1667 阅读 88评论 0喜欢 1

0. 预备知识

GCD对时间的描述有些新奇

#define NSEC_PER_SEC 1000000000ull

#define NSEC_PER_MSEC 1000000ull

#define USEC_PER_SEC 1000000ull

#define NSEC_PER_USEC 1000ull

MSEC:毫秒

USEC:微秒

NSEC:纳秒

SEC:秒

NSEC_PER_SEC,每秒有多少纳秒

USEC_PER_SEC,每秒有多少毫秒

#define NSEC_PER_SEC 1000000000ull //GCD最常用的时间描述

打现在开始往后5秒

double delayInSeconds = 5.0;

dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t) (delayInSeconds * NSEC_PER_SEC));1->开始时间,2->延后时间

1. dispatch_group

1.1 dispatch_group_notify

当多个任务在并行队列内无序的进行,需要在多个任务全部完成后立刻开启新任务,那么这时就是需要用到

dispatch_group_async与dispatch_group_notify的组合

dispatch_queue_t coucurrent_queue = dispatch_queue_create("com.pogong.www", DISPATCH_QUEUE_CONCURRENT);

dispatch_group_t group = dispatch_group_create();

dispatch_group_async(group, coucurrent_queue, ^{

for (int i = 0; i<10; i++) {

NSLog(@"group-01 - %@", [NSThread currentThread]);

}

});

dispatch_group_async(group, coucurrent_queue, ^{

for (int i = 0; i<10; i++) {

NSLog(@"group-02 - %@", [NSThread currentThread]);

}

});

dispatch_group_notify(group, coucurrent_queue,^{

NSLog(@"op finish,start new op");

});

1.2 dispatch_group_wait

还是1.1同样的需求:当任务在并行队列内无序的进行,需要在多个任务结束后立刻开启新任务

也可以用dispatch_group_async与dispatch_group_wait的组合来完成

dispatch_queue_t coucurrent_queue = dispatch_queue_create("com.pogong.www", DISPATCH_QUEUE_CONCURRENT);

dispatch_group_t group = dispatch_group_create();

dispatch_group_async(group, coucurrent_queue, ^{

for (int i = 0; i<10; i++) {

NSLog(@"group-01 - %@", [NSThread currentThread]);

}

});

dispatch_group_async(group, coucurrent_queue, ^{

for (int i = 0; i<10; i++) {

NSLog(@"group-02 - %@", [NSThread currentThread]);

}

});

dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

NSLog(@"op finish");

只是需要注意的是dispatch_group_wait会阻塞当前线程,或者说GCD的所有带_wait都会阻塞当前线程

dispatch_group_wait的第二参数为超时时间,DISPATCH_TIME_FOREVER代表一直等下去.

也可以将以上dispatch_group_wait代码换成:

int delayInSeconds = 20;

dispatch_time_t cheak_Time = dispatch_time(DISPATCH_TIME_NOW, (int64_t) (delayInSeconds * NSEC_PER_SEC));

long res = dispatch_group_wait(group, cheak_Time);

if (res == 0) {

NSLog(@"zc done");

}else{

NSLog(@"zc ing");

}

设置超时时间为20s,

1.group任务提前完成,提前返回

2.按指定时间返回

dispatch_group_wait的返回值为0代表group的任务全部完成,否则就代表任务还在进行中

1.3 dispatch_async+dispatch_group_enter+dispatch_group_leave

dispatch_group_t group = dispatch_group_create();

NSMutableArray * array = [NSMutableArray array];

for (int i=0; i<5000; i++) {

dispatch_group_enter(group);//enter和leave成对出现

dispatch_async(dispatch_get_global_queue(0, 0), ^{

NSLog(@"add in %@", [NSThread currentThread]);

[array addObject:[NSNumber numberWithInt:i]];

dispatch_group_leave(group);//enter和leave成对出现

});

}

NSLog(@"before wait %@", [NSThread currentThread]);

dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

还是1.1同样的需求:当任务在并行队列内无序的进行,需要在多个任务结束后立刻开启新任务

也可以用dispatch_async+dispatch_group_enter+dispatch_group_leaver的组合来完成

2.dispatch_after

double delayInSeconds = 5.0;

dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t) (delayInSeconds * NSEC_PER_SEC));

dispatch_after(popTime, dispatch_get_main_queue(), ^{

NSLog(@"zc after");

});

dispatch_after的用法如上方代码,就不多说了

3.信号量dispatch_semaphore

首先介绍一下信号量(semaphore)的概念。信号量是持有计数的信号,不过这么解释等于没解释。我们举个生活中的例子来看看。

假设有一个房子,它对应进程的概念,房子里的人就对应着线程。一个进程可以包括多个线程。这个房子(进程)有很多资源,比如花园、客厅等,是所有人(线程)共享的。

但是有些地方,比如卧室,最多只有两个人能进去睡觉。怎么办呢,在卧室门口挂上两把钥匙。进去的人(线程)拿着钥匙进去,没有钥匙就不能进去,出来的时候把钥匙放回门口。

这时候,门口的钥匙数量就称为信号量(Semaphore)。很明显,信号量为0时需要等待,信号量不为零时,减去1而且不等待。

此段描述完全摘自:bestswifer iOS多线程编程——GCD与NSOperation总结

3.1 多线程资源单一占用

dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);

dispatch_semaphore_t sem = dispatch_semaphore_create(1);

NSMutableArray * muArr = [NSMutableArray array];

for (int i = 0; i< 1000; i++) {

dispatch_async(q, ^{

dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);

[muArr addObject:@(i)];

NSLog(@"%d",i);

dispatch_semaphore_signal(sem);

});

}

dispatch_semaphore_create,创建一个信号量为1的信号

dispatch_semaphore_wait,只有信号量大于0才能通过dispatch_semaphore_wait,通过的同时信号量减1

dispatch_semaphore_signal,信号量加1

3.2 超时显示

- (void)downloadFile

{

_semaphore = dispatch_semaphore_create(0);

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://baobab.wdjcdn.com/14525705791193.mp4"] cachePolicy:1 timeoutInterval:30];

[[self.session downloadTaskWithRequest:request] resume];

double delayInSeconds = 5.0;

dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t) (delayInSeconds * NSEC_PER_SEC));

NSLog(@"zc wait");

long res = dispatch_semaphore_wait(_semaphore, popTime);

if (res) {

NSLog(@"zc timed out");

}else{

NSLog(@"zc timed in");

}

}

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location

{

dispatch_semaphore_signal(_semaphore);

NSLog(@"zc done");

}

还是那句所有GCD带_wait函数都会阻塞当前线程

开始下载创建信号,

下载成功,增加信号量,

任务提前完成,提前返回

按指定时间返回

dispatch_semaphore_wait的返回值为0代表任务完成,否则就代表任务还在进行中

3.3 dispatch_semaphore_wait超时时间的理解

overTime不是调用dispatch_semaphore_wait后等待的时间,而是信号量创建后的时间

-(void)overTimeTest{

dispatch_semaphore_t signal = dispatch_semaphore_create(0);

double delayInSeconds = 5.0;

dispatch_time_t overTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t) (delayInSeconds * NSEC_PER_SEC));

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

NSLog(@"1 start wait");

dispatch_semaphore_wait(signal, overTime);

NSLog(@"需要线程同步的操作1 开始");

dispatch_semaphore_signal(signal);

});

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

sleep(3);

NSLog(@"2 start wait");

dispatch_semaphore_wait(signal, overTime);

NSLog(@"需要线程同步的操作2");

dispatch_semaphore_signal(signal);

});

}

以上两个block内的dispatch_semaphore_wait调用相差3秒,但执行dispatch_semaphore_wait却是同时的.

4.dispatch_barrier_async

多个线程对内存中的数组或是字典进行读的操作是OK,

但如果多个线程对内存中的数组或是字典进行读+写的操作,就会有问题

NSMutableArray * muArr = [NSMutableArray array];

[muArr addObject:@"1"];

[muArr addObject:@"2"];

[muArr addObject:@"3"];

dispatch_queue_t con_queue = dispatch_queue_create("com.pogong.www", DISPATCH_QUEUE_CONCURRENT);

dispatch_async(con_queue, ^{

NSLog(@"%@",muArr);

});

dispatch_async(con_queue, ^{

NSLog(@"%@",muArr);

});

dispatch_barrier_async(con_queue, ^{

NSLog(@"add add add");

[muArr addObject:@"4"];

});

dispatch_async(con_queue, ^{

NSLog(@"%@",muArr);

});

dispatch_async(con_queue, ^{

NSLog(@"%@",muArr);

});

dispatch_barrier_async很好解决了多线程读写安全进行的问题,

在原有的多线程执行时,加入一个dispatch_barrier_async,

会像有栅栏一样挡住多线程执行,而先执行dispatch_barrier_async,

在执行完dispatch_barrier_async之后,再继续多线程的操作

5. dispatch_source

Dispatch Source用于监听系统的底层对象,比如文件描述符,Mach端口,信号量等。主要处理的事件如下表

DISPATCH_SOURCE_TYPE_DATA_ADD   数据增加

DISPATCH_SOURCE_TYPE_DATA_OR    数据OR

DISPATCH_SOURCE_TYPE_MACH_SEND  Mach端口发送

DISPATCH_SOURCE_TYPE_MACH_RECV  Mach端口接收

DISPATCH_SOURCE_TYPE_MEMORYPRESSURE 内存情况

DISPATCH_SOURCE_TYPE_PROC   进程事件

DISPATCH_SOURCE_TYPE_READ   读数据

DISPATCH_SOURCE_TYPE_SIGNAL 信号

DISPATCH_SOURCE_TYPE_TIMER  定时器

DISPATCH_SOURCE_TYPE_VNODE  文件系统变化

DISPATCH_SOURCE_TYPE_WRITE  文件写入

方法

dispatch_source_create:创建dispatch source,创建后会处于挂起状态进行事件接收,需要设置事件处理handler进行事件处理。

dispatch_source_set_event_handler:设置事件处理handler

dispatch_source_set_cancel_handler:事件取消handler,就是在dispatch source释放前做些清理的事。

dispatch_source_cancel:关闭dispatch source,这样后续触发的事件时不去调用对应的事件处理handler,但已经在执行的handler不会被取消.

5.1 dispatch_source_set_timer

UITableView在被拖拽时NSTimer就不起作用了

必须加[[NSRunLoop currentRunLoop] addTimer:anyTimer forMode:NSRunLoopCommonModes];

而dispatch source timer与runloop是没有关系的,所以可以放心使用

dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,0, 0, DISPATCH_TARGET_QUEUE_DEFAULT);

dispatch_source_set_event_handler(source, ^(){

NSLog(@"sourceTimer Time log");

});

dispatch_source_set_timer(source, DISPATCH_TIME_NOW,5*NSEC_PER_SEC,1*NSEC_PER_SEC);//1->源,2->开始时间,3->间隔时间,4->误差秒数

_source = source;

dispatch_resume(_source);

5.2 文件监听

监视文件夹内文件变化

NSURL * directoryURL = [NSURL URLWithString:_path]; // assume this is set to a directory

int const fd = open([[directoryURL path] fileSystemRepresentation], O_EVTONLY);

if (fd < 0) {

char buffer[80];

strerror_r(errno, buffer, sizeof(buffer));

NSLog(@"Unable to open \"%@\": %s (%d)", [directoryURL path], buffer, errno);

return;

}

dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, fd,

DISPATCH_VNODE_WRITE | DISPATCH_VNODE_DELETE, DISPATCH_TARGET_QUEUE_DEFAULT);

dispatch_source_set_event_handler(source, ^(){

unsigned long const data = dispatch_source_get_data(source);

if (data & DISPATCH_VNODE_WRITE) {

NSLog(@"The directory changed.");

}

if (data & DISPATCH_VNODE_DELETE) {

NSLog(@"The directory has been deleted.");

}

});

dispatch_source_set_cancel_handler(source, ^(){

close(fd);

});

_source = source;

dispatch_resume(_source);

还要注意需要用DISPATCH_VNODE_DELETE去检查监视的文件或文件夹是否被删除,如果删除了就停止监听

6. dispathc_once

dispathc_once函数可以确保某个 block 在应用程序执行的过程中只被处理一次,而且它是线程安全的。所以单例模式可以很简单的实现,写单例必备

+ (Manager *)sharedInstance {

static Manager *sharedManagerInstance = nil;

static dispatch_once_t once;

dispatch_once($once, ^{

sharedManagerInstance = [[Manager alloc] init];

});

return sharedManagerInstance;

}

7. dispathc_apply

7.1 并行队列完成任务,开启新任务

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_apply(10, queue, ^(size_t index) {

NSLog(@"%d\n",index);

});

NSLog(@"done");

打印结果为:

2017-03-04 21:40:43.454 GCDTrain[1289:42894] 0

2017-03-04 21:40:43.454 GCDTrain[1289:42937] 3

2017-03-04 21:40:43.454 GCDTrain[1289:42940] 2

2017-03-04 21:40:43.454 GCDTrain[1289:42894] 4

2017-03-04 21:40:43.454 GCDTrain[1289:42894] 5

2017-03-04 21:40:43.454 GCDTrain[1289:42938] 1

2017-03-04 21:40:43.455 GCDTrain[1289:42894] 8

2017-03-04 21:40:43.454 GCDTrain[1289:42940] 6

2017-03-04 21:40:43.455 GCDTrain[1289:42937] 7

2017-03-04 21:40:43.455 GCDTrain[1289:42938] 9

2017-03-04 21:40:43.455 GCDTrain[1289:42894] done

所以这又是一种对多线程无序的限定的API,dispatch_applyblock内的所有任务被执行完之后才会执行后面的代码,当然dispatch_apply与前面提到的所有带_wait的API一样都是阻塞当前线程的

dispatch_apply与带_wait的API也有不同,dispatch_apply比较适合做些重复的+执行次数确定的任务

7.2 防止开启线程过多

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

for (int i = 0; i < 999; i++){

dispatch_async(queue, ^{

NSLog(@"%d,%@",i,[NSThread currentThread]);

});

}

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_apply(999, queue, ^(size_t i){

NSLog(@"%d,%@",i,[NSThread currentThread]);

});

看两份代码的打印结果可知道,不用dispatch_apply的并行+异步会开启许多线程,而我们已经知道:「使用太多线程会导致消耗大量内存」,所以在这种场景下应该使用dispatch_apply

8.dispatch_set_target_queue

8.1dispatch_set_target_queue可以设置queue的优先级

dispatch_queue_create创建队列的优先级跟global dispatch queue的默认优先级一样,假如我们需要设置队列的优先级,可以通过dispatch_set_target_queue方法

dispatch_queue_t serialQueue = dispatch_queue_create("com.pogong.www", DISPATCH_QUEUE_SERIAL);

dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0);

dispatch_set_target_queue(serialQueue, globalQueue);

//这样serialQueue的优先级和globalQueue的优先级一样

8.2 定义队列层级关系

将多个队列用dispatch_set_target_queue设置为某个串行队列的下属队列,可以防止并行执行

  • 加队列层级关系

dispatch_queue_t targetQueue = dispatch_queue_create("target_queue", DISPATCH_QUEUE_SERIAL);

dispatch_queue_t queue1 = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);

dispatch_queue_t queue2 = dispatch_queue_create("queue2", DISPATCH_QUEUE_CONCURRENT);

dispatch_set_target_queue(queue1, targetQueue);//加层级关系

dispatch_set_target_queue(queue2, targetQueue);//加层级关系

dispatch_async(queue1, ^{

NSLog(@"do job1");

});

dispatch_async(queue2, ^{

NSLog(@"do job2");

});

dispatch_async(queue2, ^{

NSLog(@"do job3");

});

dispatch_async(queue2, ^{

NSLog(@"do job4");

});

dispatch_async(queue2, ^{

NSLog(@"do job5");

});

dispatch_async(queue2, ^{

NSLog(@"do job6");

});

2017-03-04 22:07:40.723 GCDTrain[1400:51089] do job1

2017-03-04 22:07:40.723 GCDTrain[1400:51089] do job2

2017-03-04 22:07:40.724 GCDTrain[1400:51089] do job3

2017-03-04 22:07:40.724 GCDTrain[1400:51089] do job4

2017-03-04 22:07:40.724 GCDTrain[1400:51089] do job5

2017-03-04 22:07:40.725 GCDTrain[1400:51089] do job6

  • 不加队列层级关系

dispatch_queue_t queue1 = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);

dispatch_queue_t queue2 = dispatch_queue_create("queue2", DISPATCH_QUEUE_CONCURRENT);

dispatch_async(queue1, ^{

NSLog(@"do job1");

});

dispatch_async(queue2, ^{

NSLog(@"do job2");

});

dispatch_async(queue2, ^{

NSLog(@"do job3");

});

dispatch_async(queue2, ^{

NSLog(@"do job4");

});

dispatch_async(queue2, ^{

NSLog(@"do job5");

});

dispatch_async(queue2, ^{

NSLog(@"do job6");

});

2017-03-04 22:01:04.781 GCDTrain[1365:48597] do job2

2017-03-04 22:01:04.781 GCDTrain[1365:48598] do job1

2017-03-04 22:01:04.781 GCDTrain[1365:48599] do job3

2017-03-04 22:01:04.781 GCDTrain[1365:48609] do job5

2017-03-04 22:01:04.781 GCDTrain[1365:48608] do job4

2017-03-04 22:01:04.782 GCDTrain[1365:48597] do job6

打印结果一目了然

9. dispatch IO

在书上,在别人的文章里对dispatch IO都是一段引用苹果官方的代码,跑不起来,自己真会用了再说

10. 未完待续

还有很多API并未见过介绍,所以.....

文章参考:

Objective-C高级编程:iOS与OS X多线程和内存管理

bestswifer iOS多线程编程——GCD与NSOperation总结

戴铭 细说GCD如何用

写在最前面:
转自:https://blog.csdn.net/wpeng20125/article/details/73650569
对原文作了下排版利于理解,也感谢原文作者为我们说明这个函数

dispatch_time_t 类型,它的创建有两个函数

    1. dispatch_time(<#dispatch_time_t when#>, <#int64_t delta#>)
      第一个参数是从什么时间开始,一般直接传
      DISPATCH_TIME_NOW表示从现在开始
      第二个参数表示具体的时间长度(不能直接传 int 或 float), 可以写成这种形式 (int64_t)3* NSEC_PER_SEC
        #define NSEC_PER_MSEC 1000000ull    每毫秒有1000000纳秒
#define USEC_PER_SEC 1000000ull 每秒有1000000微秒
#define NSEC_PER_USEC 1000ull 每微秒有1000纳秒

注意 delta 的单位是纳秒!
1秒的写作方式可以是 1* NSEC_PER_SEC; 1000* NSEC_PER_MSEC或 USEC_PER_SEC* NSEC_PER_USEC

  • 2.dispatch_walltime(<#const struct timespec * _Nullable when#>, <#int64_t delta#>),
    第一个参数是一个结构体, 创建的是一个绝对的时间点,比如 2016年10月10日8点30分30秒, 如果你不需要自某一个特定的时刻开始,可以传 NUll,表示自动获取当前时区的当前时间作为开始时刻, 第二参数意义同第一个函数
    dispatch_time_t time = dispatch_walltime(NULL, 5* NSEC_PER_SEC);

两个函数的不同
例如:
从现在开始,1小时之后是触发某个事件

使用第一个函数创建的是一个相对的时间,第一个参数开始时间参考的是当前系统的时钟,当 device 进入休眠之后,系统的时钟也会进入休眠状态, 第一个函数同样被挂起; 假如 device 在第一个函数开始执行后10分钟进入了休眠状态,那么这个函数同时也会停止执行,当你再次唤醒 device 之后,该函数同时被唤醒,但是事件的触发就变成了从唤醒 device 的时刻开始,1小时之后.

而第二个函数则不同,他创建的是一个绝对的时间点,一旦创建就表示从这个时间点开始,1小时之后触发事件,假如 device 休眠了10分钟,当再次唤醒 device 的时候,计算时间间隔的时间起点还是,开始时就设置的那个时间点, 而不会受到 device 是否进入休眠影响

作者:zcc_ios
链接:https://www.jianshu.com/p/9e2c363a09e2
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

iOS 多线程 GCD part3:API的更多相关文章

  1. iOS多线程 GCD

    iOS多线程 GCD Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法. dispatch queue分成以下三种: 1)运行在主线程的Main que ...

  2. iOS 多线程GCD的基本使用

    <iOS多线程简介>中提到:GCD中有2个核心概念:1.任务(执行什么操作)2.队列(用来存放任务) 那么多线程GCD的基本使用有哪些呢? 可以分以下多种情况: 1.异步函数 + 并发队列 ...

  3. iOS多线程——GCD

    最近的项目遇到了很多多线程的问题,借此机会对GCD进行了一番学习并总结.首先说一下什么是GCD,GCD全称 Grand Central Dispatch,是异步执行任务的技术之一.开发者只需要定义想要 ...

  4. iOS多线程GCD详解

    在这之前,一直有个疑问就是:gcd的系统管理多线程的概念,如果你看到gcd管理多线程你肯定也有这样的疑问,就是:并发队列怎么回事,即是队列(先进先出)怎么会并发,本人郁闷了好久,才发现其实cgd管理多 ...

  5. iOS多线程——GCD篇

    什么是GCD GCD是苹果对多线程编程做的一套新的抽象基于C语言层的API,结合Block简化了多线程的操作,使得我们对线程操作能够更加的安全高效. 在GCD出现之前Cocoa框架提供了NSObjec ...

  6. ios多线程-GCD基本用法

    ios中多线程有三种,NSTread, NSOperation,GCD 这篇就讲讲GCD的基本用法 平时比较多使用和看到的是: dispatch_async(dispatch_get_global_q ...

  7. iOS多线程——GCD与NSOperation总结

    很长时间以来,我个人(可能还有很多同学),对多线程编程都存在一些误解.一个很明显的表现是,很多人有这样的看法: 新开一个线程,能提高速度,避免阻塞主线程 毕竟多线程嘛,几个线程一起跑任务,速度快,还不 ...

  8. iOS多线程GCD的使用

    1. GCD 简介 Grand Central Dispatch(GCD)是异步执行任务的技术之一.一般将应用程序中记述的线程管理用的代码在系统级中实现.开发者只需要定义想执行的任务并追加到适当的Di ...

  9. iOS多线程GCD的简单使用

    在iOS开发中,苹果提供了三种多线程技术,分别是: (1)NSThread (2)NSOperation (3)GCD 简单介绍一下GCD的使用. GCD全称 Grand Central Dispat ...

随机推荐

  1. netcore OA权限管理系统

    下载

  2. SciPy fftpack(傅里叶变换)

    章节 SciPy 介绍 SciPy 安装 SciPy 基础功能 SciPy 特殊函数 SciPy k均值聚类 SciPy 常量 SciPy fftpack(傅里叶变换) SciPy 积分 SciPy ...

  3. java多线程(待完善)

    1.小型系统 // 线程完成的任务(Runnable对象)和线程对象(Thread)之间紧密相连 class A implements Runnable{ public void run(){ // ...

  4. [U53204] 树上背包的优化

    题目链接 本文旨在介绍树上背包的优化. 可见例题,例题中N,M∈[1,100000]N,M \in [1,100000]N,M∈[1,100000]的数据量让O(nm2)O(nm^2)O(nm2)的朴 ...

  5. 019、MySQL取本季度开始时间和本季度结束时间

    SELECT QUARTER ( adddate( dy, ) ) QTR, date_add( dy, INTERVAL MONTH ) Q_start, adddate( dy, ) Q_end ...

  6. JAVA面试题0 JAVA语言的基本知识

    JAVA语言的特点是什么? >面向对象:两个基本概念:类和对象:三大基本特性:封装.继承.多态: >健壮性:java吸收了C/C++的优点,但是去掉了它们影响健壮性的部分,例如指针和内存申 ...

  7. python假设一段楼梯共 n(n>1)个台阶,小朋友一步最多能上 3 个台阶,那么小朋友上这段楼 梯一共有多少种方法

    我们先把前四节种数算出来(自己想是哪几类,如果你不会算,那就放弃写代码吧,干一些在街上卖肉夹馍的小生意,也挣得不少) 标号 1    2    3     4 种类 1    2    4     7 ...

  8. C++ mfc 简易文本编辑器 遇到的一些问题

    [题目40]简易文本编辑器. 设计一个简易的文本编辑器. 设计要求: (1) 具有图形菜单界面: (2) 查找,替换(等长,不等长),插入(插串,文本块的插入).文本块移动(行块,列块移动),删除; ...

  9. HTML文本域(文本框)禁止修改写入数据方法

    html文本域有时需要禁止修改内容,方法如下: 加入readonly=""或readonly="readonly" 如下:<input name=&quo ...

  10. CAN通讯基本设置

    A节点pelican协议下,扩展帧 单滤波方式 A节点的接收滤波器 ID号 设置为 0x19881205 设置过程 (1) pelican模式设置 设置时钟分频寄存器CDR.7 =1 使SJA1000 ...