首页 文章 精选 留言 我的

精选列表

搜索[知识管理],共10000篇文章
优秀的个人博客,低调大师

学会这几个知识点可以救命

第一次写代码 不要害怕这件事情,写代码,其实和写作文一样,首先需要有一个题目,然后对题目进行拆解。至于文采,也就是代码漂不漂亮就是另一回事了。相信很多读者看过很多Python基础入门的书籍,或者购买了很多Python的视频课,但还是不知道怎么写代码。其中的原因只有一个,就是编码的思路没有转变。 转变Python编码思路的唯一一个方法就是实战。只有在实战中你才能发现:代码因为少或者多了一个字母,或者是代码中用的是中文字符而不是英文字符导致没有出现预期结果;代码可以运行,没有语法错误,但结果却不是自己想要……但是当你通过模仿其他人的代码运行得到结果后,是不是也很有成就感。然后慢慢自己能学会设计代码,还有可能去教别人写代码。将模仿代码变成设计代码,最后能够自己写代码。 总之,我们的目标就是,给定任何一个开发项目,你脑中立即有编码思路,剩下的就是动手写一下代码而已。 数据--程序的原材料 在开始编码之前,我们需要明白两件事情:一是编码规则;二是什么是数据。 本文的编码指的是编写Python高级编程语言。既然是语言,肯定有语法,并且也需要素材,你可以把它想成汉语或者英语,语言的语法就相当于编码的规则,这也是Python的编程基础。等基础语法完成时,我们就可以进入项目实战阶段。 接着介绍一下数据。 简单地说,数据就是在计算机中的任何东西,比如音乐、电影、文章等。Python编程就是利用自己的语法规则对其进行加工处理,然后呈现出想要的数据结果。所以你可以把程序或者代码看成一个服装加工厂:布料就是程序中使用的数据,机器就是根据语法处理数据,衣服就是代码输出的结果。 有时数据太多,不好理解。对其进行分类是一个方法,非常便于理解与处理。Python数据类型如下表所示。 学会写注释,方便你我他 注释就是在代码里添加的解释说明。代码是告诉阅读的人做什么事情,而注释是告诉阅读的人为什么这么做。这点在学习编程时特别重要,尤其在刚开始时一定要养成写注释的习惯,不要嫌麻烦,因为注释便于阅读代码的人理解。 在实际工作中,项目一般都很大,需要协作完成。如果没写注释就给下一个人阅读,那么阅读就可能变成一件特别痛苦的事情。有时候代码漂不漂亮也要看注释是不是全面。不过目前的普遍状况是,国内很多程序员,即使是工作了很多年的老程序员也不喜欢写注释。因为麻烦,他们认为这是多干活。这个观点是错误的,因为即使是自己写的代码,几年以后可能自己都不记得写的是什么了。另外,一些大公司代码注释写得都非常全面,比如Google、Oracle等。 在Python中,单行注释用井号(#)表示,注释就是#后面的内容;多行注释用一对三引号(''' ''')或者一对三个双引号(""" """)表示。单行注释一般用于某一行的解说说明,而多行注释一般用于整个文本或者某一个代码区域的解释说明,其中三个双引号表示对整个文档的说明。对于这些注释,Python解释器不会执行具体的内容。在下面的例子中,Python解释器会忽略注释,只输出Hello World。 例子:多行注释与单行注释 """ 本章为第三天内容:夯实基础的内容 主要包括: 数据类型 变量等 """ ''' 此处是多行注释 可以写很多行 ''' # 打印输出Hello World! # 注意:请在#与注释内容中间留一个空格 print('Hello World!') 运行结果如下所示。 Hello World! 注意:并不是每一行代码都需要注释,只有关键的地方才需要注释,例如,新的语法点、代码重点解决的问题、重要的细节、结论等。 常量与变量 常量,顾名思义就是值不能被改变的量,比如5、10等数字或者一个字符串的文本。 与常量相对应的就是变量,顾名思义就是值一直在改变的量。因为值在改变,我们需要给它取一个名字,也就是标识符。在Python编程中,我们把标识符称为变量名,并且使用等号(=)把变量名和值关联起来,具体的语法是: 变量名 = 值 例子: # 定义变量,并使用print()函数打印出来 # my_name是变量名,刘德华为值 # 变量名不变,值可以变,比如值换成周杰伦 my_name = "刘德华" print(my_name) my_name = "周杰伦" print(my_name) 运行结果如下所示。 刘德华 周杰伦 注意:变量存在内存中。Python语言对大小写敏感,例如my_name与My_name对于Python语言来说是两个不同的变量。 变量命名规则 变量命名是有一定规则的。如果违背了规则,则会出错,具体规则如下所示。 变量名只能以字母或下画线开头,不能以数字开头,但是可以以数字结尾。 例子: ''' 变量规则介绍: 第一个语句错误; 第二个语句正确''' 3_log = 'This is a log file' log_3 = 'This is a log file' 运行结果如下所示。 3_log = 'This is a log file' ^ SyntaxError: invalid token 变量名不能包含空格,否则认为是语法错误。比如my name是错误的,解决方法是使用下画线(_)连接起来,变成my_name。 不能用Python中的关键字作为变量名。**变量命名方法** 在符合变量命名规则的前提下,变量名最好简短、易懂,即从变量名就能看出其代表的意思。比如my_name肯定比a好懂(千万不要使用a、b、c做变量名)。 当变量需要用两个以上单词表示时,常用的命名方法有两种。 第一种命名方法 驼峰式大小写,即第一个单词的首字母小写,第二个单词的首字母大写,例如firstName、lastName。也可以每一个单词的首字母都采用大写,例如FirstName、LastName、CamelCase。它也被称为Pascal命名法。 第二种命名方法 两个单词不能直接用连字符(-)或者空格连接,但是可以使用下画线连接,比如first_name、last_name。

优秀的个人博客,低调大师

java 面试知识点笔记(十)多线程与并发-原理 上篇

问:线程安全问题的主要诱因? 存在共享数据(也称临界资源) 存在多条线程共同操作这些共享数据 解决方法:同一时刻有且只有一个线程在操作共享数据,其他线程必须等到该线程处理完数据后再对共享数据进行操作 互斥锁的特征: 互斥性:即在同一时间只允许一个线程持有某个对象锁,通过这种特性来实现多线程协调机制,这样在同一时间只有一个线程对需要同步的代码块(复合操作)进行访问。互斥性也称为操作的原子性。 可见性:必须确保在锁被释放之前,对共享变量所做的修改,对于随后获得该锁的另一个线程是可见的(即在获得锁时应该获得最新共享变量的值),否则另一个线程可能是在本地缓存的某个副本上继续操作,从而引起不一致。 ps:synchronized 锁的不是代码,锁的是对象 获取锁的分类:获取对象锁、获取类锁 获取对象锁的两种用法: 同步代码块(synchronized(this),synchronized(类实例对象)),锁是小括号中的实例对象 同步非静态方法(synchronized method) 锁是当前对象的实例对象 获取类锁的两种用法: 同步代码块(synchronized(类.class)),锁是小括号中的类对象(Class对象) 同步非静态方法(synchronized static method) 锁是当前对象的类对象(Class对象) 类锁和对象锁在锁同一个对象的时候表现行为是一样的,因为class也是对象锁,只是比较特殊,所有的实例共享同一个类(同一个class对象) 如果锁的是不同对象(同一个class的不同实例)表现就不一样了,类锁是全同步的,对象锁是按对象区分同步的 类锁和对象锁互不干扰的,因为对象实例和类是两个不同的对象 对象锁和类锁的终结: 有线程访问对象的同步代码块时,另外的线程可以访问该对象的非同步代码块 若锁住的是同一个对象,一个线程在访问对象的同步代码块时,另一个访问对象的同步代码块的线程会被阻塞 若锁住的是同一个对象,一个线程在访问对象的同步方法时候另一个访问对象同步方法的线程会被阻塞 若锁住的是同一个对象,一个线程在访问对象的同步代码块时,另一个线程访问对象同步方法会被阻塞,反之亦然 同一个类的不同对象锁互不干扰 类锁由于是一种特殊的对象锁,因此表现和上述1、2、3、4一致,而由于一个类只有一把对象锁,所以同一个类的不同对象使用类锁将会是同步的 类锁和对象锁互不干扰 乐观锁 乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,采取在写时先读出当前版本号,然后加锁操作(比较跟上一次的版本号,如果一样则更新),如果失败则要重复读-比较-写的操作。 java中的乐观锁基本都是通过CAS操作实现的,CAS是一种更新的原子操作,比较当前值跟传入值是否一样,一样则更新,否则失败。 悲观锁 悲观锁是就是悲观思想,即认为写多,遇到并发写的可能性高,每次去拿数据的时候都认为别人会修改,所以每次在读写数据的时候都会上锁,这样别人想读写这个数据就会block直到拿到锁。java中的悲观锁就是Synchronized,AQS框架下的锁则是先尝试cas乐观锁去获取锁,获取不到,才会转换为悲观锁,如RetreenLock。 阻塞代价 java的线程是映射到操作系统原生线程之上的,如果要阻塞或唤醒一个线程就需要操作系统介入,需要在户态与核心态之间切换,这种切换会消耗大量的系统资源,因为用户态与内核态都有各自专用的内存空间,专用的寄存器等,用户态切换至内核态需要传递给许多变量、参数给内核,内核也需要保护好用户态在切换时的一些寄存器值、变量等,以便内核态调用结束后切换回用户态继续工作。 如果线程状态切换是一个高频操作时,这将会消耗很多CPU处理时间; 如果对于那些需要同步的简单的代码块,获取锁挂起操作消耗的时间比用户代码执行的时间还要长,这种同步策略显然非常糟糕的。 synchronized会导致争用不到锁的线程进入阻塞状态,所以说它是java语言中一个重量级的同步操纵,被称为重量级锁,为了缓解上述性能问题,JVM从1.5开始,引入了轻量锁与偏向锁,默认启用了自旋锁,他们都属于乐观锁。 深入理解synchronized底层实现原理: Java对象头和Monitor是实现synchronized的基础 hotspot中对象在内存的布局是分3部分 对象头 实例数据 对其填充 这里主要讲对象头:一般而言synchronized使用的锁对象是存储在对象头里的,对象头是由Mark Word和Class Metadata Address组成 要详细了解java对象的结构点击:https://blog.csdn.net/zqz_zqz/article/details/70246212 mark word存储自身运行时数据,是实现轻量级锁和偏向锁的关键,默认存储对象的hasCode、分代年龄、锁类型、锁标志位等信息。 mark word数据的长度在32位和64位的虚拟机(未开启压缩指针)中分别为32bit和64bit,它的最后2bit是锁状态标志位,用来标记当前对象的状态,对象的所处的状态,决定了markword存储的内容,如下表所示: 由于对象头的信息是与对象定义的数据没有关系的额外存储成本,所以考虑到jvm的空间效率,mark word 被设计出一个非固定的存储结构,以便存储更多有效的数据,它会根据对象本身的状态复用自己的存储空间(轻量级锁和偏向锁是java6后对synchronized优化后新增加的) Monitor:每个Java对象天生就自带了一把看不见的锁,它叫内部锁或者Monitor锁(监视器锁)。上图的重量级锁的指针指向的就是Monitor的起始地址。 每个对象都存在一个Monitor与之关联,对象与其Monitor之间的关系存在多种实现方式,如Monitor可以和对象一起创建销毁、或当线程获取对象锁时自动生成,当线程获取锁时Monitor处于锁定状态。 Monitor是虚拟机源码里面用C++实现的 源码解读:_WaitSet 和_EntryList就是之前学的等待池和锁池,_owner是指向持有Monitor对象的线程。当多个线程访问同一个对象的同步代码的时候,首先会进入到_EntryList集合里面,当线程获取到对象Monitor后就会进入到_object区域并把_owner设置成当前线程,同时Monitor里面的_count会加一。当调用wait方法会释放当前对象的Monitor,_owner恢复成null,_count减一,同时该线程实例进入_WaitSet集合中等待唤醒。如果当前线程执行完毕也会释放Monitor锁并复位对应变量的值。 接下来是字节码的分析: package interview.thread; /** * 字节码分析synchronized * @Author: cctv * @Date: 2019/5/20 13:50 */ public class SyncBlockAndMethod { public void syncsTask() { synchronized (this) { System.out.println("Hello"); } } public synchronized void syncTask() { System.out.println("Hello Again"); } } 然后控制台输入 javac thread/SyncBlockAndMethod.java 然后反编译 javap -verbose thread/SyncBlockAndMethod.class 先看看syncsTask方法里的同步代码块 从字节码中可以看出 同步代码块 使用的是 monitorenter 和 monitorexit ,当执行monitorenter指令时当前线程讲试图获取对象的锁,当Monitor的count 为0时将获的monitor,并将count设置为1表示取锁成功。如果当前线程之前有这个monitor的持有权它可以重入这个Monnitor。monitorexit指令会释放monitor锁并将计数器设为0。为了保证正常执行monitorenter 和 monitorexit 编译器会自动生成一个异常处理器,该处理器可以处理所有异常。主要保证异常结束时monitorexit(字节码中多了个monitorexit指令的目的)释放monitor锁 ps:重入是从互斥锁的设计上来说的,当一个线程试图操作一个由其他线程持有的对象锁的临界资源时,将会处于阻塞状态,当一个线程再次请求自己持有对象锁的临界资源时,这种情况属于重入。就像如下情况:hello2也是会输出的,并不会锁住。 再看看syncTask同步方法 解读:这个字节码中没有monitorenter和monitorexit指令并且字节码也比较短,其实方法级的同步是隐式实现的(无需字节码来控制)ACC_SYNCHRONIZED是用来区分一个方法是否同步方法,如果设置了ACC_SYNCHRONIZED执行线程将持有monitor,然后执行方法,无论方法是否正常完成都会释放调monitor,在方法执行期间,其他线程都无法在获得这个monitor。如果同步方法在执行期间抛出异常而且在方法内部无法处理此异常,那么这个monitor将会在异常抛到方法之外时自动释放。 java6之前Synchronized效率低下的原因: 在早期版本Synchronized属于重量级锁,性能低下,因为监视器锁(monitor)是依赖于底层操作系统的的MutexLock实现的。 而操作系统切换线程时需要从用户态转换到核心态,时间较长,开销较大 java6以后Synchronized性能得到了很大提升(hotspot从jvm层面做了较大优化,减少重量级锁的使用): Adaptive Spinning 自适应自旋 Lock Eliminate 锁消除 Lock Coarsening 锁粗化 Lightweight Locking 轻量级锁 Biased Locking偏向锁 …… 自旋锁: 许多情况下,共享数据的锁定状态持续时间较短,切换线程不值得 通过让线程执行while循环等待锁的释放,不让出CPU java4就引入了,不过默认是关闭的,java6后默认开启的 自旋本质和阻塞状态并不相同,如果锁占用时间非常短,那自旋锁性能会很好 缺点:若锁被其他线程长时间占用,会带来许多性能上的开销,因为自旋一直会占用CPU资源且白白消耗掉CPU资源。 如果线程超过了限定次数还没有获取到锁,就该使用传统方式挂起线程(可以设置VM的PreBlockSpin参数来更改限定次数) 引用阅读:https://blog.csdn.net/zqz_zqz/article/details/70233767

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册