知识点

小知识点

OSI参考模型

  • 物理层
    集线器
  • 数据链路层
    网卡,交换机
  • 网络层(IP协议)
    选择合适的网间路由和交换结点,确保数据及时传送,将从下层接收到的数据进行IP地址的封装与解封装。常把这一层数据叫做数据包,主要设备:路由器。
  • 传输层(TCP/UDP协议)
    定义了一些传输数据的协议和端口,如TCP、UDP协议,主要将从下层接收的数据进行分段和传输,到达目的地址后再进行重组,以往把这一层数据叫做段。
    TCP(传输控制协议)
    我给你发了个东西+收到了+好的(这个如果没有的话,那么当过期的数据撞到服务器时,就会建立连接,但如果有第三次,就会再次确认一下)
    SYN:SYN=0时,表示同步序号,用来建立连接。SYN标志位和ACK标志位搭配使用,当连接请求的时候,SYN=1,ACK=0;连接被响应的时候,SYN=1,ACK=1;
    UDP(用户数据报协议):
    只负责发出去,但不保证你收到
    可靠性,速度,连接的有无,传输数据大小
  • 会话层
  • 表示层
    主要是进行对接收的数据进行解释(如图片、声音等)
  • 应用层(HTTP/FTP协议)
    FTP(各种文件下载)、浏览器、QQ等

HTTP

  • 无状态:对之前的请求是无记忆的。
  • 无连接:一次请求和响应,之后就会断开连接

四叉树:

Linux中一个端口能够接受tcp链接数量的理论上限

无上限

linux socket使用16bit无符号整型表示端口号,但端口号可复用,所以一个客户端最多建立65536个socket连接不对。

进程

资源分配的最小单位,每个进程都有独立的代码和数据空间(进程上下文)

线程

并发调度运行的基本单位。线程间相互独立,可以各自独立运行在不同的处理器上。同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC)。

多线程编程

这里写图片描述
- 继承Thread

class Thread1 extends Thread{  
    private String name;  
    public Thread1(String name) {  
       this.name=name;  
    }  
    public void run() {  
        for (int i = 0; i < 5; i++) {  
            System.out.println(name + "运行  :  " + i);  
            try {  
                sleep((int) Math.random() * 10);  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
        }  

    }  
}  
public class Main {  

    public static void main(String[] args) {  
        Thread1 mTh1=new Thread1("A");  
        Thread1 mTh2=new Thread1("B");  
        mTh1.start();  
        mTh2.start();  

    }  

}  
  • 实现Runnable接口
package com.multithread.runnable;  
class Thread2 implements Runnable{  
    private String name;  

    public Thread2(String name) {  
        this.name=name;  
    }  

    @Override  
    public void run() {  
          for (int i = 0; i < 5; i++) {  
                System.out.println(name + "运行  :  " + i);  
                try {  
                    Thread.sleep((int) Math.random() * 10);  
                } catch (InterruptedException e) {  
                    e.printStackTrace();  
                }  
            }  

    }  

}  
public class Main {  

    public static void main(String[] args) {  
        new Thread(new Thread2("C")).start();  
        new Thread(new Thread2("D")).start();  
    }  
}  

不管是扩展Thread类还是实现Runnable接口来实现多线程,最终还是通过Thread的对象的API来控制线程的,熟悉Thread类的API是进行多线程编程的基础。
main方法其实也是一个线程。在java中所以的线程都是同时启动的,至于什么时候,哪个先执行,完全看谁先得到CPU的资源。
在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个jVM实习在就是在操作系统中启动了一个进程。

public class MyRunnable implements Runnable {
    private int ticket = 10;
    private String name;

    public void run() {
        for (int i = 0; i < 500; i++) {
            if (this.ticket > 0) {
                System.out.println(Thread.currentThread().getName() + "卖票---->" + (this.ticket--));
            }
        }
    }

}

public class RunnableDemo {

    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();

        Thread t1 = new Thread(myRunnable, "一号窗口");
        Thread t2 = new Thread(myRunnable, "二号窗口");
        Thread t3 = new Thread(myRunnable, "三号窗口");
        t1.start();
        t2.start();
        t3.start();
    }
}

运行结果:

一号窗口卖票—->10
一号窗口卖票—->8
二号窗口卖票—->9
一号窗口卖票—->7
二号窗口卖票—->6
一号窗口卖票—->5
二号窗口卖票—->4
二号窗口卖票—->2
二号窗口卖票—->1
一号窗口卖票—->3

多线程共享一个资源tickt,共同处理一个任务。但结果数字并不是顺序打印,是因为打印有可能有延迟所致。

  • 总结
    实现Runnable接口比继承Thread类所具有的优势:
    1:适合多个相同的程序代码的线程去处理同一个资源
    2:可以避免java中的单继承的限制
    3:增加程序的健壮性,代码可以被多个线程共享,代码和数据独立
    4:线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类

多线程

  • 同一进程的各线程间共享数据,一次同步会复杂。
  • 内存占用少,切换简单
  • 编程复杂
  • 一个线程挂掉将导致整个进程挂掉
  • 适应于多核分布式,进程主要多机分布式。
  • 本来是一核一处理器,但现在intel能进行乱序快速模拟两个核。

进程间通信方式

  • 管道
    无名管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用.进程的亲缘关系一般指的是父子关系。无明管道一般用于两个不同进程之间的通信。当一个进程创建了一个管道,并调用fork创建自己的一个子进程后,父进程关闭读管道端,子进程关闭写管道端,这样提供了两个进程之间数据流动的一种方式。
  • 消息队列
  • 共享内存+信号量
    映射一段能被其他进程访问的共享内存+同步计数器
  • 信号
    用于通知接收进程某个事件已经发生
  • 套接字
    适合于客户端和服务器端之间信息实时交互;可以加密,数据安全性强;需对传输的数据进行解析,转化成应用级的数据

线程间通信方式

主要是线程同步,无数据交换通信机制。

  • 锁机制
    条件变量+互斥锁
    读写锁:对写互斥
  • 信号量机制
  • 信号机制

什么时候用多线程

  • 频繁创建销毁的优先用线程
  • 切换频繁。需要进行大量计算的优先使用线程
  • 强相关的处理用线程,弱相关的处理用进程
    Server:消息收发、消息处理。
    “消息收发”和“消息处理”就是弱相关的任务,而“消息处理”里面可能又分为“消息解码”、“业务处理”,这两个任务相对来说相关性就要强多了。因此“消息收发”和“消息处理”可以分进程设计,“消息解码”、“业务处理”可以分线程设计。
    当然这种划分方式不是一成不变的,也可以根据实际情况进行调整。

LRU

内存管理的页面置换算法

强连通图

强连通图(Strongly Connected Graph)是指在有向图G中,如果对于每一对vi、vj,vi≠vj,从vi到vj和从vj到vi都存在路径,则称G是强连通图

编译的五个过程

  1. 词法分析
  2. 语法分析
  3. 词义分析+记号系统
  4. 优化(不同编译器不同)
  5. 目标代码

单继承

一个类不能继承多个父类

分支预测

CPU在判断if语句时提前会对不同分支均run,来提高运行速度

观察者模式

  • 当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
  • 当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变。
  • 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的。

页面传递对象方法

  • request的url
  • session
  • cookie
  • application

java.lang.Throwable

Error

内存溢出,线程死锁等系统问题

  • IOError
  • VirtualMachineError

Exception

java.lang.RuntimeException之外

强制检查
用户的问题,他再鼓捣鼓捣能克服写代码时必须(try catch)

  • IOException
  • SQLException
  • NoSuchFieldException
java.lang.RuntimeException

非检查
程序员的问题,软件系统就没编对

  • ArrayIndexOutOfBoundsException
  • ClassCastException
  • NullPointerException
  • NoSuchElementException
  • UnknownElementException
  • IllegalStateException

关键字互斥锁

布局管理器

  • Border
    将版面划分成东、西、南、北、中五个区域,将添加的组件按指定位置放置。
  • Flow
    组件按从左到右而后从上到下的顺序依次排列,一行不能放完则折到下一行。
  • Grid
    矩形网格形式对容器的组件进行布置
  • GridBag
    以表格形式布置容器内的组件,将每个组件放置在每个单元格内,而一个单元格可以跨越多个单元格合并成一个单元格,即多个单元格可以组合成一个单元格,从而实现组件的自由布局。
  • Card
    以层叠的方式布置组件,如同很多张卡片叠在一起,从而只能看到最上面的那一张卡片
  • Box
    以嵌套式盒子来管里容器的布局,通过将组件放入水平或垂直形盒子以多层嵌套的方式进行布局。

HashMap/HashTable

  • 历史原因
    HashTable是陈旧的Dictionary类;而HashMap是java1.2引进的Map接口的实现。
  • 安全性
    HashTable是线程安全的,同步的;而HashMap不是。

  • HashMap允许键为空或值为空;HashTable不允许。

Vector/ArrayList

  • 安全性
    Vector是线程安全的,同步的;而ArrayList不是。
  • 数据增长
    当需要数据增长(都有add方法)时,Vector默认增长为原来的一倍;ArrayList是一半。

Collection/Collections

这里写图片描述
Collections,Arrays都是是辅助的静态方法类。

Set

不能有内容相同的对象(所以地址相同的对象更不能有)

List

可以重复add同一个对象

length

  • array.length
  • string.length()

补码

如果先判断符号再后续处理,会让电路设计的异常复杂。,人们想到了让符号位也参与运算的设计。

  • 机器数
    有符号的二进制数,用最高位存储符号。

    10000011的真值为+3
    00000011的真值为-3

  • 原码

    [+1]原 = 0000 0001
    [-1]原 = 1000 0001

  • 反码
    正数的反码=本身
    负数的反码=原码符号位不变,其余各个位取反.

    [+1] = [00000001]原 = [00000001]反
    [-1] = [10000001]原 = [11111110]反

  • 补码
    正数的补码=本身
    负数的补码=反码+1)

    [+1] = [00000001]原 = [00000001]反 = [00000001]补
    [-1] = [10000001]原 = [11111110]反 = [11111111]补

  • 用原码

    1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2

  • 用反码

    1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原= [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 = -0

虽然人们理解上+0和-0是一样的, 但是0带符号是没有任何意义的. 而且会有[0000 0000]原和[1000 0000]原两个编码表示0.

  • 用补码
    1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]补 + [1111 1111]补 = [0000 0000]补=[0000 0000]原
    (-1) + (-127) = [1000 0001]原 + [1111 1111]原 = [1111 1111]补 +
    [1000 0001]补 = [1000 0000]补
    这样0用[0000 0000]表示, 而以前出现问题的-0则不存在了.而且可以用
    [1000 0000]表示-128
    8位二进制, 使用原码或反码表示的范围为[-127, +127], 而使用补码表示的范围为[-128, 127]

==/equals

  • ==是比较值是否相等;equals是一个方法,比较内容是否相同
  • Object中
viod equals(Object a){
    return this==a;
}

try catch语句

String

在java中String类为什么要设计成不可变?

主要是String里所有的方法都小心翼翼地不去改那个数组成员。
而这样子字符串就会近似int等基本类型的不可变性(immutable !=final)。

编译时优化

String s1 = "a";//s1的字面量是“a”
String s2 = s1 + "b";
String s3 = "a" + "b";
System.out.println(s2 == "ab");//false
System.out.println(s3 == "ab");//true,地址都相同

编译可以对字符串常量直接相加的表达式进行优化,不必要等到运行期去进行加法运算处理,而是在编译时去掉其中的加号,直接将其编译成一个这些常量相连的结果。

String s="a"+"b"+"c"+"d";//定义了一个对象,而不是5个。

相当于直接定义了一个”abcd”的字符串。

源码

/*
返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。 
如果 oldChar 在此 String 对象表示的字符序列中没有出现,则返回对此 String 对象的引用。否则,创建一个新的 String 对象,它所表示的字符序列除了所有的 oldChar 都被替换为 newChar 之外,与此 String 对象表示的字符序列相同。 

示例: 

"mesquite in your cellar".replace('e', 'o')
         returns "mosquito in your collar"

 */
    public String replace(char oldChar, char newChar) {
        if (oldChar != newChar) {
            int len = value.length;
            int i = -1;
            char[] val = value; /* avoid getfield opcode */

            while (++i < len) {
                if (val[i] == oldChar) {
                    break;
                }
            }
            if (i < len) {
                char buf[] = new char[len];
                for (int j = 0; j < i; j++) {
                    buf[j] = val[j];
                }
                while (i < len) {
                    char c = val[i];
                    buf[i] = (c == oldChar) ? newChar : c;
                    i++;
                }
                return new String(buf, true);
            }
        }
        return this;
    }

Interger/Int

int a=2;
int b=2;
System.out,println(a==b);//true
Interger c=new Interger(2);
Interger d=new Interger(3);
System.out,println(c==d);//false
System.out,println(a==c);//false

final

  • 修饰类
    仅仅是不能被继承
  • 修饰变量
    只能赋值一次

immutable

  • 基本数据类型的重要性质
  • 线程安全,因为不可变

堆与栈

一个类分成员函数以及成员变量。

  • 类有以下变量类型:
    1. 成员变量被static修饰,也叫类变量
    2. 成员变量不被static修饰,也叫实例变量
    3. 成员函数中的变量,叫局部变量
  • 类变量在堆里
  • 实例变量在栈里
  • 局部变量也在栈里
    Student s=new Student();中局部变量s在生命期结束时会被s及其值(16进制数字)销毁,但new的Student实例还在堆中没被释放,依然被GC监视并决定何时销毁。
  • new 出了来的对象在堆上
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值