最近给组里的小伙伴作了一次培训,分享了一些编程的基础和自我学习编程的方法。感受对你们可能有用,里面颇有很面试常常问到的基础相关的东西,想分享给大伙。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
js的V8虚拟机和上面两种有点像,可是又很不相同:JavaScript中全部的数据都是存放在堆内存中,为了基本数据类型和引用数据类型的理解区分开来。面试
值类型和引用类型 算法
Q:为何阿里巴巴Java开发手册不建议在for循环中使用“+”进行字符串拼接? 数据库
A:String是一个对象,且对象一旦被建立就是固定不变的了,对String对象的任何改变都不影响到原对象,全部一直在建立和销毁对象,改变指针的指向,浪费内存和性能。咱们可使用StringBuilder和StringBuffer,他们是可变的。编程
GC垃圾回收c#
垃圾回收的几种方式 设计模式
**GC调优:**不少次面试的时候有问道,gc垃圾回收的调优,你又了解嘛?
线程不安全
线程不安全:就是不提供数据访问保护,有可能出现多个线程前后更改数据形成所获得的数据是脏数据。
Q: i++是线程安全吗? A: 是不安全的
每一个线程都有本身的工做内存,每一个线程须要对共享变量操做时必须先把共享变量从主内存 load 到本身的工做内存,等完成对共享变量的操做时再 save 到主内存。好比上面的i,是先拷贝到线程中的,而后作完++之后,不是很及时的刷新到主存。
问题就出在这了,若是一个线程运算完后还没刷到主内存,此时这个共享变量的值被另一个线程从主内存读取到了,这个时候读取的数据就是脏数据了,它会覆盖其余线程计算完的值。
线程安全必要条件
原子性:跟数据库事务的原子性概念差很少,即一个操做(有可能包含有多个子操做) 要么所有执行(生效),要么所有都不执行(都不生效)。
可见性:当多个线程并发访问共享变量时,一个线程对共享变量的修改, 其它线程可以当即看到。可见性问题是好多人忽略或者理解错误的一点。
顺序性:是程序执行的顺序按照代码的前后顺序执行。
原子性解决:保证操做原子性的工具是锁和同步方法(或者同步代码块)。使用锁,能够保证同一时间只有一个线程能拿到锁,也就保证了同一时间只有一个线程能执行申请锁和释放锁之间的代码。 Java中的synchronized、c#中的lock
可见性解决:volatile关键字来保证可见性。当使用volatile修饰某个变量时,它会保证对该变量的修改会当即被更新到内存中,所以其它线程须要读取该值时必须从主内存中读取,从而获得最新的值。
高并发,目前比较流行的有两种,一种为多线程的方式(java中后台就是这样的),一种是事件驱动,异步IO(node中是这样的)。
高并发-多线程
线程的在操做系统的调度中,某个时刻,只能将资源让给一个线程。而线程的上下文的切换,会有很大的消耗。
高并发-异步IO
只有一个线程,没有上下文的切换消耗,可是只有一个线程干活。
选择场景若是 IO时间多,那异步IO效率高,选择场景若是 计算时间多,那同步IO效率高。Nginx 和 Node就是基于这种模式
经常使用的数据结构
时间复杂度
这个方法须要 (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… 能够的话,给个星星哦!