从学代码到跑路

最近给组里的小伙伴作了一次培训,分享了一些编程的基础和自我学习编程的方法。感受对你们可能有用,里面颇有很面试常常问到的基础相关的东西,想分享给大伙。java

计算机基础篇

首先看三段代码,分别为JS代码、C#代码和Java代码。有:局部变量、全局变量,值类型和引用类型,静态和常量、线程(JS没有)。node

// 定义了一个Person类
function Person(id,name,age){
  this.id = id;
  this.name = name;
  this.age = age;
}
function test(){
  // 局部变量
  let id = 0;
  console.log(id);
}
// 全局变量
var person = new Person(100,'梁先生',25);
test();
复制代码
// 定义了一个Person类
public class Person {  
  // 常量
  public const string CodeTest = "梁先生"// 静态变量
  public static int Code = 0; 
  // 私有变量
  private int testId;
  public void add(){
    // 局部变量
    int temp = 0;
    testId++;    
  }
}

// 线程类
public class Count implements Runnable{
  Person person;
  public Count(Person person){
      this.person = person;
  }    
  @Override
  public void run(){
     person.add();
  }
}

var person = new Person(100,'梁先生',25);
// 多线程的问题
int threadCount = 100;
for(int i = 0; i<threadCount;i++){
    ThreadMsDeal = new Thread(new Count(person));
	ThreadMsDeal.Start();
}
复制代码
// 定义了一个Person类
public class Person{
  // 常量
  public const string CodeTest = "梁先生";
  // 静态变量
  public static int Code = 0; 
    
  // 定义了一个私有变量
  private testId = 0;
  public Person(id,name,age){
    this.id = id;
    this.name = name;
    this.age = age;
  }
    
  public int id {get;set;}
  public string name{get;set;}
  public int age{get;set;}
    
  public void test(){
    // 局部变量
    int temp = 0;
    testId++;    
  }
}

var person = new Person(100,'梁先生',25);
// 多线程的问题
int threadCount = 100;
for(int i = 0; i<threadCount;i++){
    ThreadMsDeal = new Thread(new ThreadStart(test));
	ThreadMsDeal.Start();
}
复制代码

上面代码中的数据类型都能在下方的图找到对应。 git

数据类型

怎么分配的呢

JVM和CLR和很相似,使用JVM来讲明 github

JVM

  • new 的引用类型的值存在堆中。
  • 普通值类型的如int啥的放在栈中。
  • const的值是在编译期间肯定的,所以只能在声明时经过常量表达式指定其值。
  • static限定,意味着“无论类的对象被建立多少次,都只有一个实例”  。
  • 本地方法栈:虚拟机使用到的Native 方法服务。
  • 常量和静态变量都是放在方法区里面的,这个区域也对全部线程共享。

js的V8虚拟机和上面两种有点像,可是又很不相同:JavaScript中全部的数据都是存放在堆内存中,为了基本数据类型和引用数据类型的理解区分开来。面试

V8
文字总结内存

值类型和引用类型 算法

值类型的内存分配

引用类型的内存分配

Q:为何阿里巴巴Java开发手册不建议在for循环中使用“+”进行字符串拼接? 数据库

String

A:String是一个对象,且对象一旦被建立就是固定不变的了,对String对象的任何改变都不影响到原对象,全部一直在建立和销毁对象,改变指针的指向,浪费内存和性能。咱们可使用StringBuilder和StringBuffer,他们是可变的。编程

GC垃圾回收c#

垃圾回收

  • 若是不进行垃圾回收,内存早晚都会被消耗空
  • 内存溢出:就是你要求分配的内存超出了系统能给你的,系统不能知足需求,因而产生溢出
  • 内存泄漏:是指你向系统申请分配内存进行使用(new),但是使用完了之后却不回收

垃圾回收的几种方式 设计模式

标记清除:后会产生大量不连续的内存碎片

标记-整理算法:GC暂停的时间会增加,须要将全部的对象都拷贝到一个新的地方,并更新它们的地址

复制算法:须要一块能容纳下全部存活对象的额外的内存空间,可一次性分配的最大内存缩小了一半

跳过

**GC调优:**不少次面试的时候有问道,gc垃圾回收的调优,你又了解嘛?

  1. 不要显式调用GC的回收函数,好比:Java中的 System.gc()、C#中的析构(2次回收)
  2. 尽可能减小临时对象的使用(不使用的变量就给删掉)
  3. 对象不用时最好显式置为Null
  4. 不用大量的String来字符串拼接
  5. 能用基本类型如Int,Long,就不用Integer,Long对象
  6. 尽可能少用静态对象变量,由于静态变量只有在程序结束时才释放
  7. 分散对象建立或删除的时间,好比避免:new 类[10000]

线程不安全

线程不安全

不安全

图

线程不安全:就是不提供数据访问保护,有可能出现多个线程前后更改数据形成所获得的数据是脏数据。

Q: i++是线程安全吗? A: 是不安全的

jvm的线程模型

每一个线程都有本身的工做内存,每一个线程须要对共享变量操做时必须先把共享变量从主内存 load 到本身的工做内存,等完成对共享变量的操做时再 save 到主内存。好比上面的i,是先拷贝到线程中的,而后作完++之后,不是很及时的刷新到主存。

问题就出在这了,若是一个线程运算完后还没刷到主内存,此时这个共享变量的值被另一个线程从主内存读取到了,这个时候读取的数据就是脏数据了,它会覆盖其余线程计算完的值。

线程安全必要条件

必要条件

原子性:跟数据库事务的原子性概念差很少,即一个操做(有可能包含有多个子操做) 要么所有执行(生效),要么所有都不执行(都不生效)。

可见性:当多个线程并发访问共享变量时,一个线程对共享变量的修改, 其它线程可以当即看到。可见性问题是好多人忽略或者理解错误的一点。

顺序性:是程序执行的顺序按照代码的前后顺序执行。

解决办法

原子性解决:保证操做原子性的工具是锁和同步方法(或者同步代码块)。使用锁,能够保证同一时间只有一个线程能拿到锁,也就保证了同一时间只有一个线程能执行申请锁和释放锁之间的代码。 Java中的synchronized、c#中的lock

可见性解决:volatile关键字来保证可见性。当使用volatile修饰某个变量时,它会保证对该变量的修改会当即被更新到内存中,所以其它线程须要读取该值时必须从主内存中读取,从而获得最新的值。

高并发,目前比较流行的有两种,一种为多线程的方式(java中后台就是这样的),一种是事件驱动,异步IO(node中是这样的)。

高并发-多线程

多线程

线程的调度

线程的在操做系统的调度中,某个时刻,只能将资源让给一个线程。而线程的上下文的切换,会有很大的消耗。

高并发-异步IO

异步IO

事件队列

只有一个线程,没有上下文的切换消耗,可是只有一个线程干活。

选择场景若是 IO时间多,那异步IO效率高,选择场景若是 计算时间多,那同步IO效率高。Nginx 和 Node就是基于这种模式

经常使用的数据结构

  • 数组(数组不要定义太长,由于须要连续的空间。不够的时候会引发GC)
  • 栈(递归的时候利用的是栈)
  • 队列(日志的读写分离)
  • 链表
  • 树 (菜单递归建树、数据库索引)
  • 哈希表(查询数据快,只须要一次哦)

时间复杂度

时间复杂度

这个方法须要 (n + 1 + n + 1) = 2n + 2 次运算。咱们通常会把系数和尾巴去掉,由于在n趋近无穷大的时候,系数和尾巴都不咋起做用,差不了多少。故:时间复杂度为:O(n)

void Func(int n) {
    for(int i = 0; i < n; i++) {         
        for(int j = 0; j < n; j++) {       
            printf("Hello, World!\n");      
        }
    }
}
复制代码

时间复杂度为:O(n × n × 1),即 O(n^2)。:

数据结构的时间复杂度

数据结构的时间复杂度

时间复杂度的图像,根据本身的编码状况选择对应的数据结构

时间复杂度的图表

你们能够对比一下,在x轴趋于无穷大时,x为数据量,而O(1)和log(n)的y值还只是1或者很小很小,y为查询的操做的次数。因此你们能够选择必定的数据结构来优化本身的代码


面向对象篇

在编码的时候去理解和运用一下三个特征。由于培训例子是举的工做中的例子,不咋好拿代码出来说解。在咱们发现有相同的代码的时候,咱们是能够抽象出来的。还有一个是:对接口编程,而不是对实现编程。

面向对象

五大原则也是须要必定的编码去支撑,而后才能本身的理解

五大原则

还有经常使用的设计模式,这个也是很重要的,须要掌握经常使用的,由于时间问题,不在这里讲解。

总结篇

这个是我的总结,和语言无关,和框架无关。我的仍是以为基础仍是很重要的,若是你懂基础,在代码优化,和出问题的时候去排查,站的角度是不同的。

可能涉及到的书或者知识点比较多,可是没有必要全看完整的东西 ,只须要掌握基础,经常使用的知识点便可。不经常使用的东西,或者都不会涉及到的东西就不用看。

不少如代码重构,优化,是能够一直贯穿在整个图中的。

编程学习

下方是是我的的一些学习方法和常常看到一些知识点的出处。

学习方法

但愿能帮助到你们,谢谢!

github.com/liangwei010… 能够的话,给个星星哦!

相关文章
相关标签/搜索