我的知识集锦

1、关于ArrayList与LinkedList的比较分析
  ArrayList底层采用数组实现,LinkedList底层采用双向链表实现。
当执行插入或者删除操作时,采用LinkedList比较好
当执行搜索操作时,采用ArrayList比较好。
2、当向LinkedList添加一个对象时,实际上LinkedList内部会生成一个Entry对象,该对象的结构为:
Entry
{
Entry previous;
Object element;
Entry next;
}


Map(映射):Map的keySet()方法会返回key的集合,因为Map的键是不能重复的,因此keySet()的方法返回类型是Set;而Map的值是可以重复的,因此value()方法的返回类型是Collection,可以容纳重复的元素。


策略模式的定义
        定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。
        策略模式使这些算法在客户端调用它们的时候能够互不影响地变化。
策略模式的组成
抽象策略角色:策略类,通常由一个接口或者抽象类实现
具体策略角色:包装相关的算法和行为
环境角色:持有一个策略类的引用,最终给客户端调用的
策略模式的编写步骤
1、对策略对象定义一个公共接口
2、编写策略类,该类实现了上面的公共接口
3、在使用策略对象的类中保存一个对策略对象的引用
4、在使用策略对象的类中,实现对策略对象的set和get方法(注入)或者使用构造方法完成赋值
策略模式的缺点
1、客户端必须要知道所有的策略类,并自行决定使用哪一个策略类
2、造成很多的策略类
解决方法
采用工厂方法


HashMap底层维护一个数组,我们向HashMap中所放置的对象实际上是存储在该数组当中的。


当向hashMap中put一对键值时,它会根据key的hashCode值计算出一个位置,该位置就是此对象准备往数组中存放的位置。


如果该位置没有对象存在,就将此对象直接放进数组当中;如果该位置已经有对象存在了,则顺着此存在的对象的链开始寻找(Entry类有一个Entry类型的next成员变量,指向了该对象的下一个对象),如果此链上有对象的话,再去使用equals方法进行比较,如果对此链上的某个对象的equals方法比较为false,则将该对象放到数组当中,然后将数组当中该位置以前存在的那个对象链接到此对象的后面。


输入\输出流:从外部流向程序(输入),从程序流向外部的(输出)


程序在使用数据时所扮演的角色有两个:一个是源,一个是目的。


从功能上分有两大流:输入和输出流。
从流结构上可分为字节流(以字节为处理单位或称面向字节)和字符流(以字符为处理单位或称面向字符),字符流的底层还是用字节流去实现的,字符流只是对字节流的一个包装。


字节流的输入流和输出流基础是InputStream和OutoutStream这两个抽象类。不能new出来它们的实例
字符流输入输出的基础是抽象类Reader和Writer


读数据的逻辑为:
open a stream
while more information
read information
close the stream


写数据的逻辑为:
open a stream
while more information
write  information
close the stream


装饰模式是在不必改变原类文件的和使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。


装饰模式的角色:
抽象构件角色:给出一个抽象接口,以规范准备接受附加责任的对象。
具体构件角色:定义一个将要接受附加责任的类。
装饰角色:持有一个构件对象的引用,并定义一个与抽象构件接口一致的接口。
具体构件角色:负责给构件对象贴上附加的责任。




装饰模式的特点:
装饰对象和真实对象有相同的接口
装饰模式包含一个真实对象的引用
装饰对象接受手游来自客户端的请求。他把这些请求转发给真实的对象。
装饰对象可以在转发这些请求以前或以后增加一些附加功能。这样酒啊确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。在面对对象的设计中,通常是通过继承来实现对给定类的功能拓展


InputStreamReader和OutoutStreamWriter类:
用来在字节流和字符流之间搭一座"桥",




 序列化(serialization)是把一个对象的状态写入 一个字节流的过程。当你想要把你的程序状态存到一个固定的存储区域例如文件时,他是很管用的。


丛文件将对象加载到内存中叫做反序列化。


一个类要想被序列化,则要实现java.io.Serializable接口,该接口没有定义任何方法,是一个标示性接口(Marker interface),当一个类实现了该接口,就表示这个类的对象是可以序列化的。
当一个对象被序列化时,只保存对象的非静态变量,不能保存任何方法的成员方法和静态的成员变量。
如果一个对象的成员变量是一个对象,那么这个对象的数据成员也会被保存。
如果一个可序列化的对象包含对某个不可序列化的对象的引用,那么整个序列化操作将会失败,并且抛出一个NotSerializableException。我们可以将这个引用标记为transient,那么对象依旧可以序列化。


在序列化时,static变量是无法序列化的;






多线程(Multi-Thread):
线程概念:就是程序中单独顺序的流控制。线程本身不能运行,他只能用于程序中。
线程的生命周期










进程与线程的区别
多个进程的内部数据和状态是完全独立的,而多线程是共享一块内存空间和一组系统资源,有可能互相影响。
线程本身的数据通常只有寄存器数据,以及一个程序执行时使用的堆栈,所以线程的切换比进程切换的负担要少。


多线程编程的目的,就是“最大限度地利用CPU资源”,当某一线程的处理不需要占用CPU而只和I/O等资源打交道时,让需要占用CPU资源的其他线程有机会获得CPU资源。从根本上说,这就是多线程编程的最终目的。


java中如果我们自己没有产生线程,那么系统就会给我们产生一个线程(主线程,main方法就在主线程上运行),我们的程序就是由线程来执行的。


进程:执行当中的程序(程序是静态的概念,进程是动态的概念)


线程的实现:在java中通过run方法为线程指明要完成的任务,有两种技术来为线程提供run方法。
1、继承Thread类并重写run方法
2、通过定义实现Runnable接口的类进而实现run方法。


将我们希望线程执行的代码方法放到run方法中,然后通过startt方法来启动线程,start首先为线程的执行准备好系统资源,然后去调用run方法。当某个系统继承了Thread类之后,该类就叫做一个线程类。


一个进程至少要包含一个进程。


对于单核CPU来说,某一个时刻只能由一个线程在执行(微观串行),从宏观角度来看,多个线程在同时执行(宏观并行)。


对于双核或双核以上的CPU来说,可以真正做到微观并行。


Thread类实现了Runnable接口,所以Thread也实现了Runnable 接口中的run方法


当生成一个线程对象时,如果没有为其设定名字,那么线程对象的名字将使用如下形式:Thread-number,该number将是自动增加的,并被所有的Thread对象所共享(因为它是static的成员变量)


当使用第一种方式来生成线程对象时,我们需要重写run方法,因为Thread类的run方法,此时什么事情都不做。
当我们使用第二种方式来生成线程对象时,我们需要实现Runnable接口的run方法,然后使用new Thread(new MyThread())(加入MyThread已经实现了Runnable接口)来生成线程对象,这时的线程对象的run方法或调用MyThread类的run方法,这样我们自己编写的run方法就执行了。


线程的实现:
总结:
线程的生命周期分为四个状态:
创建状态
可运行状态
不可运行状态
消亡状态




关于成员变量与局部变量:如果一个变量时成员变量,那么多个线程对于同一个对象的成员变量进行操作时,他们对该成员变量时彼此印象的(也就是说一个线程对成员变量的改变会影响到另一个线程 )


如果一个变量是局部变量,那么每个线程都会有一个该局部变量的拷贝,一个线程对该局部变量的改变是不会影响到
其他线程的。


停止线程的方式:不能使用Thread类的stop方法来终止线程的执行。一般要设定一个变量,在run方法中是一个循环,循环每次检查该变量,如果满足条件则继续执行,否则跳出循环,线程结束。


不能依靠线程的优先级来决定线程的执行顺序。


多线程的同步:
1、为什么要引入同步机制
在多线程环境中,可能会有两个甚至更多的线程试图同时访问一个有限的资源。必须对这种潜在资源冲突进行预防。
解决方法:
在线程使用一个资源时为其加锁即可。访问资源的第一个线程为其加上锁以后,其他线程便不能在使用这个线程,除非解锁。




Synchronized关键字:当synchronized关键字修饰一个方法的时候,该方法叫做同步方法。


java中的每一对象都有一个锁(lock)或者叫做监视器(monitor),当访问某个对象的synchronized方法时。表示将该对象上锁,此时其他任何线程都无法再去访问该synchronized方法了,知道之前的那个线程执行方法完毕后(或者是跑出了异常),纳闷将该对象的锁释放掉,其他线程才有可能再去访问该synchronized方法。


如果一个对象有多个synchronized方法,某一时刻某个线程已经进入到某个synchronized方法,那么在该方法没有执行完之前,其他线程是无法访问该对象的任何synchronized方法


如果某个synchronized方法是static的,那么当线程访问该方法时,它锁的并不是synchronized方法所在的对象,而是synchronized方法所在的对象所对应的Class对象,因为java中无论一个类有多少个对象,这些对象会对应唯一一个Class对象,因此当线程分别访问同一个类的两个对象的两个static,synchronized方法时,它们的执行顺序也是顺序的,也就是说一个线程先去执行方法,执行完毕后另一个线程才开始执行。


synchronized块,写法:
synchronized(object)
{
............................
}


synchronized方法是一种粗粒度的并发控制,某一时刻,只能有一个线程执行该synchronized方法;synchronized块则是一种细粒度的并发控制,只会将块中的同步代码,位于方法内、synchronized块之外的代码是可以被多个线程同时访问到的


wait与notify方法都是定义在Object类中,而且是final的,因此会被所有的java类继承并且无法重写。这两个方法要求在调用时线程应该已经获得了对象的锁,因此对这个两个方法的调用需要方法synchronized方法或块当中,当线程执行了wait方法时,会释放掉对象的锁。


另一个会导致线程暂停的方法就是thread 类的sleep方法,它会导致线程睡眠制定的毫秒数,但线程在睡眠的过程中是不会释放掉对象的锁的。


浅复制:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象,换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。


深复制:被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之深复制把要复制的对象所也能用的对象都复制了一遍。
TCP是Transfer Control Protocol的简称,是一种面向连接的保证可靠传输的协议。通过TCP协议传输,得到的是一个顺序的无差错的数据流。发送方和接收方的成对的两个socket之间必须建立连接,以便在TCP协议的基础上进行通信,当一个socket(通常是server socket)等待建立链接时,另一个socket可以要求进行连接,一旦这两个socket可以进行双向数据传输,双方都可以进行发送或接收数据。


UDP是User DataGram Protocol的简称,是一种无连接的协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,他在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的


两种协议的比较:
使用UDP时,每个数据报中都给出了完整的地址信息,因此无需建立发送方和接收方的连接
对于TCP协议,由于它是一个面向连接的协议,在socket之间进行数据传输之前必须要建立连接,所以在TCP中多了一个建立连接的时间。







































































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值