初始化

Python开发【第六章】:面向对象

扶醉桌前 提交于 2020-03-23 18:53:25
编程范式   编程是程序员用特定的语法+数据结构+算法组成的代码来告诉计算机如何执行任务的过程,一个程序是程序员为了得到一个任务结果而编写的一组指令的集合,正所谓条条大路通罗马,实现一个任务的方式有很多种不同的方式, 对这些不同的编程方式的特点进行归纳总结得出来的编程方式类别,即为编程范式。 不同的编程范式本质上代表对各种类型的任务采取的不同的解决问题的思路, 大多数语言只支持一种编程范式,当然也有些语言可以同时支持多种编程范式。 两种最重要的编程范式分别是面向过程编程和面向对象编程 面向过程编程   面向过程编程最易被初学者接受,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,即:将之前实现的代码块复制到现需功能处。 程序从上到下一步步执行,一步步从上到下,从头到尾的解决问题 。基本设计思路就是程序一开始是要着手解决一个大的问题,然后把一个大问题分解成很多个小问题或子过程,这些子过程再执行的过程再继续分解直到小问题足够简单到可以在一个小步骤范围内解决。 这样做的问题也是显而易见的,就是如果你要对程序进行修改,对你修改的那部分有依赖的各个部分你都也要跟着修改, 随着程序越来越大, 这种编程方式的维护难度会越来越高。 所以我们一般认为, 如果你只是写一些简单的脚本,去做一些一次性任务,用面向过程的方式是极好的,但如果你要处理的任务是复杂的,且需要不断迭代和维护的

Go语言调度器之创建main goroutine(13)

空扰寡人 提交于 2020-03-23 16:42:36
本文是《Go语言调度器源代码情景分析》系列的第13篇,也是第二章的第3小节。 上一节我们分析了调度器的初始化,这一节我们来看程序中的第一个goroutine是如何创建的。 创建main goroutine 接上一节,schedinit完成调度系统初始化后,返回到rt0_go函数中开始调用newproc() 创建一个新的goroutine用于执行mainPC所对应的runtime·main函数,看下面的代码: runtime/asm_amd64.s : 197 # create a new goroutine to start program MOVQ $runtime·mainPC(SB), AX# entry,mainPC是runtime.main # newproc的第二个参数入栈,也就是新的goroutine需要执行的函数 PUSHQ AX # AX = &funcval{runtime·main}, # newproc的第一个参数入栈,该参数表示runtime.main函数需要的参数大小,因为runtime.main没有参数,所以这里是0 PUSHQ $0 CALL runtime·newproc(SB) # 创建main goroutine POPQ AX POPQ AX # start this M CALL runtime·mstart(SB) # 主线程进入调度循环

ceph安装-monitor初始化报错

こ雲淡風輕ζ 提交于 2020-03-23 16:25:19
在安装ceph时,在执行monitor初始化mon、收集秘钥是出现异常报错 报错如下: [c2][INFO ] Running command: ceph --cluster=ceph --admin-daemon /var/run/ceph/ceph-mon.c2.asok mon_status [c2][ERROR ] admin_socket: exception getting command descriptions: [Errno 2] No such file or directory [ceph_deploy.mon][WARNIN] mon.c2 monitor is not yet in quorum, tries left: 3 [ceph_deploy.mon][WARNIN] waiting 10 seconds before retrying [c2][INFO ] Running command: ceph --cluster=ceph --admin-daemon /var/run/ceph/ceph-mon.c2.asok mon_status [c2][ERROR ] admin_socket: exception getting command descriptions: [Errno 2] No such file or directory

Java7 ConcurrentHashMap详解

五迷三道 提交于 2020-03-23 15:38:52
###Java7 ConcurrentHashMap ConcurrentHashMap 和 HashMap 思路是差不多的,但是因为它支持并发操作,所以要复杂一些。 整个 ConcurrentHashMap 由一个个 Segment 组成,Segment 代表”部分“或”一段“的意思,所以很多地方都会将其描述为分段锁。注意,行文中,我很多地方用了“槽”来代表一个 segment。 简单理解就是,ConcurrentHashMap 是一个 Segment 数组,Segment 通过继承 ReentrantLock 来进行加锁,所以每次需要加锁的操作锁住的是一个 segment,这样只要保证每个 Segment 是线程安全的,也就实现了全局的线程安全。 concurrencyLevel: 并行级别、并发数、Segment 数,怎么翻译不重要,理解它。默认是 16,也就是说 ConcurrentHashMap 有 16 个 Segments,所以理论上,这个时候,最多可以同时支持 16 个线程并发写,只要它们的操作分别分布在不同的 Segment 上。这个值可以在初始化的时候设置为其他值,但是一旦初始化以后,它是不可以扩容的。 再具体到每个 Segment 内部,其实每个 Segment 很像之前介绍的 HashMap,不过它要保证线程安全,所以处理起来要麻烦些。 ##初始化

Java8 ConcurrentHashMap详解

怎甘沉沦 提交于 2020-03-23 15:38:24
#Java8 ConcurrentHashMap Java7 中实现的 ConcurrentHashMap 说实话还是比较复杂的,Java8 对 ConcurrentHashMap 进行了比较大的改动。建议读者可以参考 Java8 中 HashMap 相对于 Java7 HashMap 的改动,对于 ConcurrentHashMap,Java8 也引入了红黑树。 说实话,Java8 ConcurrentHashMap 源码真心不简单,最难的在于扩容,数据迁移操作不容易看懂。 我们先用一个示意图来描述下其结构: 结构上和 Java8 的 HashMap 基本上一样,不过它要保证线程安全性,所以在源码上确实要复杂一些。 ##初始化 // 这构造函数里,什么都不干 public ConcurrentHashMap() { } public ConcurrentHashMap(int initialCapacity) { if (initialCapacity < 0) throw new IllegalArgumentException(); int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ? MAXIMUM_CAPACITY : tableSizeFor(initialCapacity +

ConcurrentHashMap 源码浅析 1.7

落花浮王杯 提交于 2020-03-23 15:38:18
简介 (1) 背景 HashMap死循环:HashMap在并发执行put操作时会引起死循环,是因为多线程会导致HashMap的Entry链表形成环形数据结构,一旦形成环形数据结构,Entry的next节点永远不为空,就会产生死循环获取Entry. HashTable效率低下:HashTable容器使用synchronized来保证线程安全,但在线程竞争激烈的情况下HashTable的效率非常低下.因为当一个线程访问HashTable的同步方法,其它线程也访问HashTable的同步方法时,会进入阻塞或轮询状态.如线程1使用put进行元素添加,线程2不但不能使用put方法添加元素,也不能使用get方法获取元素,所以竞争越激烈效率越低. (2) 简介 HashTable容器在竞争激烈的并发环境下表现出效率低下的原因是所有访问HashTable的线程都必须竞争一把锁,假如容器里有多把锁,每一把锁用于锁容器其中一部分数据,那么多线程访问容器里不同的数据段时,线程间不会存在竞争,从而可以有效提高并发访问效率,这就是ConcurrentHash所使用的锁分段技术.首先将数据分成一段一段地储存,然后给每一段配一把锁,当一个线程占用锁访问其中一段数据时,其它段的数据也能被其它线程访问. 结构 ConcurrentHashMap是由Segments数组结构和HashEntry数组结构组成

C++标准模板库里面的容器

ぃ、小莉子 提交于 2020-03-23 13:32:09
1. 顺序容器 sequential container 单一类型 元素组成的 有序 集合 优:顺序访问元素快 不足:添加、删除元素性能相对低 非顺序访问元素性能相对低 vector、string、array都是连续的内存空间 容器选择:取决于执行访问的操作多还是插入删除的操作多     ①一般用vector     ②空间开销很重要时,不适用链表如list、forward_list     ③需要随机访问:vector、deque     ④要在中间进行插入、删除:链表类型如list、forwad_list     ⑤只要在头尾插入、删除:deque     ⑥读取输入时要在中间插入,之后要随机访问: 输入时用vector追加数据,在调用sort()函数,以避免在中间添加元素 若必须要在中间插入元素,输入时用list,输入完成后将list的内容保存到vector中 1.1 vector    https://zh.cppreference.com/w/cpp/container/vector (1)vector的增长 vector<int> ivec; cout<<"size:"<<ivec.size()<<endl; cout<<"capacity:"<<ivec.capacity()<<endl; for(int i=0;i<20;i++) { ivec.push_back

NSDictionary初始化,使用@{}方法,插入nil时会报空指针异常

北战南征 提交于 2020-03-23 13:15:05
由于今天在NSDictionary初始化的时候出现Crash异常,故记录一下,避免下次再犯。 在Objective-C中,NSDictionary初始化的方法有很多种 方法1: [NSDictionary dictionaryWithObjectsAndKeys:<#(id), ...#>, nil] 方法2: NSDictionary *dic = @{@"key":value} 那么,坑在哪里呢?就在第二种初始化方法 NSDictionary *dic = @{@"key":value} 那它到底是如何坑的呢? 如果value是nil 的话,必将引发Crash崩溃:'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]。意思就是说使用[__NSPlaceholderDictionary initWithObjects:forKeys:count:]这个初始化方法,发现keys count和objcects的个数不匹配了 那该如何避免这个问题呢? 在使用@{@”key”:value} 这种方式初始化的时候,一定要对value做是否为nil的判断,为nil就不要加入Dictionary 或者使用标准的初始化方法

ref和out的区别

别说谁变了你拦得住时间么 提交于 2020-03-23 12:08:54
在C#中,既可以通过值也可以通过引用传递参数。通过引用传递参数允许函数成员更改参数的值,并保持该更改。若要通过引用传递参数,可使用ref或out关键字。ref和out这两个关键字都能够提供相似的功效,其作用也很像C中的指针变量。它们的区别是: 1、 使用ref型参数时,传入的参数必须先被初始化。对out而言,必须在方法中对其完成初始化。 2、 使用ref和out时,在方法的参数和执行方法时,都要加Ref或Out关键字。以满足匹配。 3、 out适合用在需要retrun多个返回值的地方,而ref则用在需要被调用的方法修改调用者的引用的时候。 注:在C#中,方法的参数传递有四种类型:传值(by value),传址(by reference),输出参数(by output),数组参数(by array)。传值参数无需额外的修饰符,传址参数需要修饰符ref,输出参数需要修饰符out,数组参数需要修饰符params。传值参数在方法调用过程中如果改变了参数的值,那么传入方法的参数在方法调用完成以后并不因此而改变,而是保留原来传入时的值。传址参数恰恰相反,如果方法调用过程改变了参数的值,那么传入方法的参数在调用完成以后也随之改变。实际上从名称上我们可以清楚地看出两者的含义--传值参数传递的是调用参数的一份拷贝,而传址参数传递的是调用参数的内存地址,该参数在方法内外指向的是同一个存储位置。

黑马程序员-----指针

爱⌒轻易说出口 提交于 2020-03-23 09:15:33
------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! ------- 第一讲 指针的基本概念 一、基本概念 内存单元的编号叫做地址。 //根据内存单元的编号或地址就可以找到所需的内存单元,所以通常把这个地址称为指针。 内存单元的指针和内存单元的内容是两个不同的概念。 总结:对于一个内存单元来说,单元的地址即为指针,其中存放的数据才是该单元的内容。 二、使用指针好处 a.为函数提供修改调用变量的灵活手段。 b.让函数有多个返回值。 //简易计算器 1 #include<stdio.h> //定义一个函数,有加,减,乘,除 2 void caculator(int x,int y, int *add , int *jian , int *cheng, float *chu){ 3 //在函数的内部访问了主调函数中的变量值 4 //加法指针变量表达式 5 *add = x + y; 6 7 //减法指针变量表达式 8 *jian = x - y; 9 10 //乘法指针变量表达式 11 *cheng = x * y; 12 13 //除法指针变量表达式 14 *chu = x /(float)y; 15 16 } 17 int main(int