🌓

shell三剑客实战

一点总结

由于自己本身就对shell中常用的命令有所了解,所以基础的就不啰嗦了。在我之前的博客中已经有不少内容

就写过的很多shell脚本经验看,最近作为助教又在跟着霍格沃兹第三期,又有了新感受。结合以前的经验,做个简单的总结。

  • 代码要规范
  • 虽然是shell,代码在逻辑上也要缜密

Linux文本三剑客

awk

最基本的作用,按规则输出列。

前置学习printf 或print。

printf

命令格式:

printf ‘匹配式’ 输入内容

它的输出全部当成字符串。所以需要自己来设置换行或空格。

%ns

输出字符串。n是数字指代输出几个字符

%ni

输出整数。n是数字自带输出几个数字。

%m.nf

输出浮点数。m是总的位数,n是小数位数

下面是例子,文本demo.txt

ID Name Linux PHP MySQL Java
1 Liming 82 55 58 87

阅读全文

mybatis入个门

MyBatis

ORMapping: Object Relationship Mapping 对象关系映射的一种流行框架。相同技术还有Hibernate。两者对比,可参考:https://www.cnblogs.com/javacatalina/p/6590321.html

ORMapping是Java 到 MySQL 的映射,开发者可以以面面向对象的思想来管理理数据库。

使用套路

两种使用方式

  • mybatis原生方式
  • mybatis动态代理

两者的区别是在获取到sqlsession链接后,操作对象的动作差异。下面举例原生的方式。之后默认用的动态代理。

1
2
3
4
// statement是mapper中的‘namespace.方法’
String statement = "com.chaosbom.mapper.AccoutMapper.save";
Account account = new Account(1L,"张三","123123",22);
sqlSession.insert(statement,account);

mapper.xml

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.chaosbom.mapper.AccoutMapper">
<insert id="save" parameterType="com.chaosbom.entity.Account">
insert into t_account(username,password,age) values(#{username},#
{password},#{age})
</insert>
</mapper>

实体对象和表

实体对象是mysql中表字段对应到java的类,通常在代码框架中被叫做entity。下面分别展示了java类和表结构。

阅读全文

SpringBoot入门系列一

官方文档https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/

阅读全文

Java多线程编程核心技术读书笔记二

这篇读书笔记是《Java多线程编程核心技术》图书的最后一篇。由于写笔记的时候已经读完了整本书,留下了一个大致的印象——适合做多线程的入门读物,所以在读完后感觉缺点什么东西,顺手就打开了另一本《Java并发编程的艺术》,瞬间感觉当年书买得十分的合理,《Java并发编程的艺术》虽然没有开始读,但是大致看了几页,感觉这本书还是要深入一些,更加贴近原理,知识的密度要高很多。

第3章 线程间通信

这一章基本围绕“wait等待/notify通知” 机制来描述线程之间通信的方式。

wait/notify

其核心思想是处理好锁的获取,锁的释放,唤醒(本质是改变线程自己的状态)的关系。

每个锁都有两个队列,一个就绪,一个阻塞。就绪是要需要锁的(可参与锁竞争),阻塞是不需要锁的(被其他事情中断而不能参与锁的争夺,notify就是改变这个队列中的线程的状态,使其进入就绪状态)

某线程调用的lock对象的wait()方法,线程释放锁,进入waiting状态(线程的等待队列);

其他线程的lock对象调用notify()或notifyall()方法,则随机或全部讲waiting该锁的线程设置回runnable可执行状态,同时线程会在完成自己代码的执行后,释放自己占用的lock(注意不是notify动作的时候释放)。等待队列中的线程则被cpu随机调用执行。

这里要题外话,书上描述“如果线程抢占到cpu资源…………”,这个描述很容易让新手误解线程是主动的,实际上并不是,是线程自己的状态配置被其他获取到cpu资源的线程改变了,然后被cpu调用到了才对。

wait(long)可以加时间参数,等带long时间看看有没有被唤醒,超过long就自动唤醒。

使用wait/notify,需要避免混乱:如过早通知、等待条件发生改变

生产/消费者模式

生产者和消费者数量在{1,N}的笛卡尔积的组合,如何处理好同步。主要是利用wait/notify的技巧。

还介绍了以下管道进行线程间的通信。这个之前了解比较少就专门记录一下。

  • PipedInputStream 和 PipedOutputStream,通过各自对象的connect(stream)方法建立进和出通道的联系
  • PipedReader 和PipedWriter,同上

线程的join方法

线程若需要其他线程等待自己线程结束,可以使用的方法。为什么要等?比如等子线程执行后返回值。是被等待的线程调用join()方法来阻塞等待线程。join()具有使线程排队运行的作用,与synchronized的区别:join内部使用的wait()方法进行等待,而synchronized是使用的对象监视器做同步。

join(long) 同wait(long)。

join(long) 和sleep(long) 区别。锁释放阻塞和和锁持有等待(阻塞)。

阅读全文

Java多线程编程核心技术读书笔记一

题记

在B站上看到马士兵老师讲解美团研发死亡七连问的视频,讲课中听到马老师的一句鸡汤,“往深了学,往宽了学”,被马老师深厚的技术功底和探求精神折服。遂,翻出了买了很久但是还没有读的《java多线程编程核心技术》和《java并发编程的艺术》,选择了简单入门的《java多线程编程核心技术》读了起来。之前买了没有去看,因为觉得并发编程对我来说太深了,我还没到那个层次,所以书都没有打开过。这次在家待业,学了一些基础的jvm原理,不再恐惧了。翻出来,一天看了2章,并没有觉得看不懂。恩,我可能是低估了自己能力。所以计划4天把书看完,并整理出笔记。先看书,再行笔记。看书过程中,如果有看不懂或理解不上来的,直接就敲了代码了。所以本笔记,没有代码。

并发问题的来源

本节内容纯属自编自导,非教程内容,不做质保。

最根本的原因是cpu运算速度远超其他存储设备,每一次脉冲就是它的一次总线宽度的二进制信号变换,变换的规则都烙印在了硬件当中,为了便于控制,形成了很多叫指令的命令(多次脉冲组合),有些指令是原子的不可再分,有些则可以再分开(不知道描述是否准确)。

进程(线程)和CPU的关系是,被CPU执行,进程和线程是被动的,它要达到什么目的,只能写到自己身上,安静的等着CPU来调度的时候由CPU来解析后被执行。个人觉得理解这点很重要。

人们为了挖掘计算机最大的算力,而设计了一套多线程机制,多个线程一起干活。多线程之间存在“公共资源”的情况。多线程的运行机制大致是,以java为例,代码编译成字节码,加载到jvm成为指令,指令被jvm翻译给cpu执行。这些个线程中的代码指令集合(编码后最终的底层指令)就开始等待cpu的时间片来宠幸自个。但是对于这些个指令来说,它是没有权利控制CPU什么时候来找你的。这就导致了,虽然线程内部的指令执行是线性的,但是多线程和线程之间的指令可就不是有顺序的,它们之间彼此交叉,是随机的,这种随机推进一步就是线程告知CPU的信息也是随机的。既然出现了顺序的随机性,在“公共资源”的情形下,就需要同步机制来控制线程的执行顺序执行。至于为什么要同步……恩,哲学问题。线程之间同步信息方可行为达预期。

一句话,时间片分配的随机性、共同资源需要顺序执行是并发问题的主要来源。高并发下,只要高级语言中的代码被转换成的指令不是原子的指令,就可能出现线程的同步问题。

第1章 多线程技能

介绍了进程线程的关系,入门级的,就不记了。以后会深化理解。

多线程的使用姿势

怎么申明多线程。

  • extend Thread 覆盖run方法
  • implement Runnable 实现run方法

Thread的构造法中支持实现了Runnble接口的类,恩,面向抽象的体现。

一些常见方法:

  • Thread.currentThread()可以获取当前线程。
  • isAlive() 判断线程是否处于活动状态
  • Thread.sleep() 休眠(暂停执行)当前线程,不会让出锁
  • getId()获取线程的唯一标识

停止线程需要说的。

阅读全文

Spring框架入个门

计划覆盖一些常见的框架,首选spring boot,在这之前先学习spring基础原理。大致了解后再进入spring boot。所以,spring去学习的时候不会过于纠结太深入的内容。大致了解原则,这篇内容就是这套逻辑下的笔记内容。看了2套视频,前后花了6天时间。

以下内容结合了个人理解整理而成,不保证描述完全准确。

初识Spring

面向接口编程、解耦。私有变量只申明,但不new对象,变量用它的接口。

Spring解决企业级开发的痛点,数不清的类之间的相互关系,委托给Spring来管理。用个术语:装配。

Bean实际上是Spring中负责加载具体业务对象的类。Spring提供了装配类对象实例的机制。这套机制是IOC\AOP的思想,对应的具体实现是DI(依赖注入)和java的注解实现的AOP和aspectJ实现的AOP。

在学习spring过程中,突发灵感,认识到计算机世界中,context是多么的重要。context在这里我表征软件执行的环境、输入条件、依赖等前置因素。所有的代码,都是在进程开始启动过程中,完成初始化、环境构造、代码执行这么一套流程的。大体,这是目前我所理解的软件的抽象。

Spring配置类注解作为入口,把类加载到运行时中(默认是单例模式,可控制),类和类之间的组合关系,实现相同接口的接口实现之间的如何区分。都提供了注解机制。

注入和装配的套路

入门级的套路:xml配置和注解基本上在自己可控源码的化效果是等价的。在第三方的源码上,利用xml方式。

Spring的在做注入时,秉着一条“傻瓜”原则,只要spring的容器中某类的实例只有一个,那么只要你告诉(配置xml和注解)spring
那么,就会自动去绑定。如果有多个,设定必要的标识(名称、顺序等)区分也就完成了绑定工作。

注解的套路

下面的注解是入门级的示意。

1
2
3
4
5
6
7
8
9
10
11
12
13
#需要被Spring加载标识
@Component @Controller @Service @Repository

# 解决歧义(让引擎识别相同接口不同的实现对象,或者相同类的不同bean,靠名称或默认类名首字母小写)
@Autowired(required=true)
#相同接口的区分手段之一
@Qualifier
# java原生的区别手段
@Resource

# 引入外部类不方便使用Componet等时,可以加注解
# 被加了备注的方法,会自动去运行时环境中查找参数涉及的类的实例
@Bean

阅读全文

java动态代理

本文是学习Spring框架的副产品。Spring中的AOP涉及动态代理的原理。

什么是代理

定义:给目标对象提供一个代理对象,并由代理对象控制对目标对象的引用;

目的:

  • 通过引入代理对象的方式来间接访问目标对象,以防止直接访问目标对象给系统带来的不必要的复杂性;
  • 通过代理对象对原有业务进行增强

代理设计模式

https://www.runoob.com/design-pattern/proxy-pattern.html

静态代理不能解决代码冗余的问题。一般不推荐静态代理(代理的关系用代码直接定义,代理和被代理需要有相同的接口,被代理作为代理对象的成员变量)。

jdk机制的动态代理

动态代理有以下特点:

  • 代理对象,不需要实现接口
  • 代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)

动态代理的实现方案

  • jdk代理,通过和目标实现相同接口保证功能一致
  • cglib代理(第三方cglib库中的一套api),通过继承保证功能一致

主要涉及:

1
2
3
4
// 静态方法
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )
// 接口
public interface InvocationHandler {....}

阅读全文

数理逻辑、图灵机、冯洛伊曼

我喜欢追本溯源,渴望真理,而不至被表象迷惑。

这篇文章未写完。可能计划读一下《计算机的数学基础》这本书再写。

计算机的数学基础

形式语言与自动机理论、可计算理论、逻辑学和程序设计理论,都是研究计算模型的。它们之间也是相互关联的,共同构成了现代计算机科学技术的理论基础。这些理论都是属于数学学科的。

形式语言与自动机理论、可计算理论和逻辑学的研究都始于20世纪初叶,特别是20世纪30年代的数学家Church(邱奇)、GMel(哥德尔)、Kleene(克林)、Post(波斯特)以及Turing(图灵)等人的杰出工作催生了现代电子数字计算机的硬件和软件的诞生。

程序设计理论的研究相比则要迟一些,是20世纪后半叶现代电子数字计算机以及程序设计语言和软件诞生之后的事情了。它是专门研究程序设计语言和程序设计方法的数学理论。这些工作对于计算机科学的实践和理论的发展有着深远的影响。比如,图灵机模型就被证明是现代电子数字计算机的理论模型。这些先驱者的工作在今天看来似乎是很平常的,它们的思想渊源甚至并不为今天众多的计算机的使用者所知道。但是这些先驱者的工作确实是应该被那些从事计算机科学技术的工作者们所熟悉、所掌握的。

语言和逻辑

人类由猿进化成人,成为灵长类的智慧生物,是进化的奇迹。语言在数百万年的进化进程中,在人类这台大自然打造的“生物机器”中,也不断的进化,相互促进,形成目前人类拥有的——自然语言。

语言,我认为它的本质是承载信息的载体。它可以装载情感、请求、命令、陈述等。

自然语言是丰富而复杂的,同一句话,不同的语境、时间、预期所要传递的信息是多样的。这里面很多段子就不一一罗列了。根本原因是自然语言属于人类,它适应人类文明。自然语言的信息传递,依赖于外界环境。语言和它所传递的信息之间,没有一对一的关系,就像算命先生算命,用些模棱两可的话说给你听,还有些星座算命也是一样的,听、读的人接受信息的背景差异,导致相同语言传递的信息千差万别。

语言的诞生,促进了文明发展,萌生了逻辑、推理。先哲用语言讲理,随着理讲得越多,人们发现要讲好道理,首先要做好陈述。没有可靠的陈述作为前提,再完美的论证过程也只是空中楼阁。因此逻辑学逐渐放大研究视野,将语法和词汇承载的信息也纳入到研究范畴中。他们(我不知具体是哪些人)得出:人类使用的陈述句、疑问句、感叹句、祈使句,在着重考虑陈述和论证,就只需要陈述句了。小学学过的,各种句型互转就明白。比如:“你是谁?”,陈述句为:“我希望知道你是谁”。感叹句:“好美的女子!”,陈述句:“女子的美丽让我感叹”。

逻辑、推理进步,让自然语言作为信息传递载体做了一次丢弃,仅留下陈述句。本身语言其实就是一种和承载信息间的“指代”和“映射”。接下来对陈述句的组成部分进行拆解,仅仅做简单拆解。

代词。所谓代词就是用于代替对象的词汇,替代具体的对象出现在语句中并表示被代替的对象。比如,“月球绕地球公转,它的自转周期和地球自转周期相同”。“月球”指代我们想指代的那个对象,“它”指代月球,代词可以是指代的指代,代词的作用和语境有关。

名词。词典中约定词汇含义的方法是用一个固定句式的语句来描述它。比较简单的做法是用“某词是什么意思”的句式把词汇的含义表达出来。

谓词。一类可以将语句中其他成员建立起联系的词。“我喜欢你“,“我在写”,“我写文章”。(个人理解,可能不当)。

接下来讨论语言中的逻辑。单纯的判断你一句话是否是真或假,是没有固定结论的,因为结论依赖于说话的场景。所以,在纯逻辑层面,我们去讨论真假,就只关注语言内部的自恰性了。所以,论述的起点,它必然是整个推理的基石。在没有任何已知前提的情况下,逻辑不能给我们任何新的知识。因此必须在已经有一些已知信息的情况下,我们才能运用逻辑。题外话,基石在很多科幻电影,比如“西部世界”中很多接待员的底层都一个他们行为的基石概念。

先哲们逐步定义了一门叫数理逻辑的学科。 其研究对象是对证明和计算这两个直观概念进行符号化以后的形式系统。

https://baike.baidu.com/item/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6%E7%9A%84%E6%95%B0%E5%AD%A6%E5%9F%BA%E7%A1%80/866204?fr=aladdin

阅读全文

jenkins架构和源码分析

本文是结合写于2015年的博客jenkins源码分析获取脉络,结合自己的研究完成,较原文有所拓展和深入。

jenkins框架

architecture_jenkins

jenkins的Model对象

jenkin(实际是传承Hudson的)Model对象jenkin平台的基石,它们hold住了某一个(job、project、executor、user、buildable item、test result)的数据和状态。

每个Model对象可以和多个views绑定,view使用了Jelly来渲染HTML和对象。

Model的可执行性是通过绑定Actions对象到Model。

Model如是描述对象存在时,是通过绑定Descriptor对象到Model。

每个Model对象和一个URL对象绑定。
Stapler通过类似JSF表达式的方式来解决URL和Model Object的绑定问题。Stapler同时处理一个model和URL,然后根据object计算URL,一直重复这个动作,直到命中某个静态资源、可执行方法、视图(jsp、jelly、groovy等)。

命中可执行方法举例:

1
2
3
4
5
6
Scenario: browser sends "POST /project/jaxb/testResult HTTP/1.1"

evaluate(<root object>, "/project/jaxb/testResult")
-> evaluate(<root object>.getProject("jaxb"), "/testResult")
-> evaluate(<jaxb project object>, "/testResult")
-> evaluate(<jaxb project object>.getTestResult())

命中视图举例:

1
2
3
org.jvnet.hudson.project.testResul -> /org/jvnet/hudson/project/testResult/index.jelly

命中之后,response.forward(this,"/org/jvnet/hudson/project/testResult/index.jelly",request)

jenkins用了stapler

阅读全文

一种VPN自动设置的解决方案

将之前写过的一个小工具做了一些优化,开源出来。起了个没有任何意义的ppter。 ppter概述为什么叫ppter任性,没有意义,听着挺好听,嗯就这样。 项目地址: https://github.com/windanchaos/ppter 可用场景多地办公,没有固定IP,需办公区对办公区建立VPN,办公区和阿里云建立VPN的场景。 能节省的费用就是两条固定I...

阅读全文