1 java同步几种方法?threadlocal怎么实现。
java的同步机制
1.synchronized;
2.Object方法中的wait,notify;
3.ThreadLocal机制 来实现的。
其中synchronized有两种用法:1.对类的方法进行修饰 2.synchronized(对象)的方法进行修饰
在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量
ThreadLocal不是用来解决对象共享访问问题的,而主要是提供了保持对象的方法和避免参数传递的方便的对象访问方式。
归纳为两点:
1 每个线程中都有一个自己的ThreadLocalMap类对象,可以将线程自己的对象保持到其中,各 管各的,线程可以正确的访问到自己的对象。
2 将一个共用的ThreadLocal静态实例作为key,将不同对象的引用保存到不同线程的 ThreadLocalMap中,然后在线程执行的各处通过这个静态ThreadLocal实例的get()方法取得自己 线程保存的那个对象,避免了将这个对象作为参数传递的麻烦。
当然ThreadLocal并不能替代同步机制,两者面向的问题领域不同。同步机制是为了同步多个线程对相同资源的并发访问,是为了多个线程之间进行通信的有效方式;而ThreadLocal是隔离多个线程的数据共享,从根本上就不在多个线程之间共享资源(变量),这样当然不需要对多个线程进行同步了。所以,如果你需要进行多个线程之间进行通信,则使用同步机制;如果需要隔离多个线程之间的共享冲突,可以使用ThreadLocal,这将极大地简化你的程 序,使程序更加易读、简洁。
2 Java常用的几种设计模式
1 单例模式
该模式主要目的是使内存中保持1个对象
2 工厂模式
该模式主要功能是统一提供实例对象的引用
3 建造模式
该模式其实就是说,一个对象的组成可能有很多其他的对象一起组成的,比如说,一个对象的实现非常复杂,有很多的属性,而这些属性又是其他对象的引用,可能这些对象的引用又包括很多的对象引用。封装这些复杂性,就可以使用建造模式
4 门面模式
这个模式个人感觉像是Service层的一个翻版。比如Dao我们定义了很多持久化方法,我们通过Service层将Dao的原子方法组成业务逻辑,再通过方法向上层提供服务。门面模式道理其实是一样的。
5 策略模式
这个模式是将行为的抽象,即当有几个类有相似的方法,将其中通用的部分都提取出来,从而使扩展更容易。
3 关于Java中static和final关键字的用法总结
static通常翻译为“静态”,可用来修饰类、成员变量和方法,也可以声明一个静态块。下面分别介绍这几类用法。
1 修饰类
首先需要注意的是,普通类是不能用static来修饰的,static只能用来修饰内部类。使用static修饰内部类之后可以使用“类.内部类”实例化这个内部类的对象, 而对于其他非静态内部类,则只能先实例化外部类,然后才能调用内部类。
2 static变量
按照是否静态的对类成员变量进行分类可分两种:一种是被static修饰的变量,叫静态变量或类变量;另一种是没有被static修饰的变量,叫实例变量。静态变量与实例变量的区别主要是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而实例变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响
3 static方法
static方法也叫静态方法,也可以直接使用“类.方法()”来直接调用。但是需要注意一下几点:一是静态方法中不能使用this和super关键字;二是静态方法中不能使用非静态成员变量,也不能调用非静态方法;三是静态方法与静态变量一样都是独立于任何实例,所以静态方法不能使用abstract修饰,即static方法不能为抽象方法。
4 static块
静态块顾名思义就是使用static{}的一段代码块。静态块是在JVM加载类的时候执行的,并且只会执行一次。由于这个特性,所以在一些场景非常好用。我在项目中遇到的过的使用场景主要有在实例化一个日志对象时,使用static块;然后就是实例化一些在类中常用但不需要多次实例化的变量等
final
final有不可改变之意,可用来修饰非抽象类、非抽象成员变量和方法。下面分别总结一下其用法
1 final类
final类不能被继承,所以其中的成员变量和方法默认也是为final的。一般来说,只有在确信该类不需要再有子类,并且不会被扩展。所以一般只有在定义一个保存一些常量信息的时候才会将类声明为final类。
2 final变量
final修饰的变量将无法再被改变,即为常量。final变量在定义时可以不赋值,此时意味着该变量为null;在使用这个变量之前则必须为其赋值,否则会出错,赋值之后这个值将不会再被改变
3 final 方法
final修饰的方法不能被覆盖,所以声明为final的方法之后,该类的子类不能覆写此方法,但是可以被继承
static和final结合使用
可以同时使用static和final修饰成员变量和方法,此时的成员变量和方法可以直接用“类.名称”调用,成员变量的值不能改变,方法不能被覆写
4 java中静态变量和成员变量的区别
所属不同:
静态变量属于类,所以也称为为类变量;成员变量属于对象,所以也称为实例变量(对象变量)
在内存中位置不同:
静态变量存储于方法区里的静态区;成员变量存储于堆内存区
在内存中出现的时间不同:
静态变量随着类的加载而加载、随着类的消失而消失;
成员变量随着对象(也叫实例)的创建而存在,随着对象的消失而消失。
调用方式不同:
静态变量可以通过类名调用,也可以通过对象调用; 成员变量只能通过对象名调用。
在静态方法中是没有this关键字的,如何理解呢?
静态变量是随着类的加载而加载,this是随着对象的创建而存在。静态先于对象存在。
静态方法只能访问静态的成员变量和静态的成员方法。
非静态方法,既可以调用静态的成员变量也可以调用非静态的成员变量;
非静态方法既可以调用静态的成员方法,也可以调用非静态的成员方法。
5 基本数据类型
6 java中基本类型和字符串之间的转换
使用包装类的 toString() 方法。
使用String类的 valueOf() 方法。
一个空字符串加上基本类型,得到的就是基本类型数据对应的字符串
int——》String
int c=10;
String str2=Integer.toString(c);//方法一
String str3=String.valueOf(c);//方法2
String str4=c+"";//方法3
将字符串转换成基本类型有两种方法:
调用包装类的 parseXxx 静态方法。
调用包装类的 valueOf() 方法转换为基本类型的包装类,会自动拆箱
String test1="happy";
int c1=Integer.parseInt(test1);//方法一
int c2=Integer.valueOf(test1);//方法二
Doubledob=1.1;
String dob1=Double.toString(dob);
Double dob2=Double.valueOf(test1);
7 时间格式
使用format()方法将日期转化为指定格式的文本
Date d = newDate();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String today = sdf.format(d);
System.out.println(today)
代码中的 “yyyy-MM-dd HH:mm:ss” 为预定义字符串, yyyy 表示四位年, MM 表示两位月份, dd 表示两位日期, HH 表示小时(使用24小时制), mm 表示分钟, ss 表示秒,这样就指定了转换的目标格式,最后调用 format() 方法将时间转换为指定的格式的字符串。
使用parse()方法将文本转换为日期
String day = "2018年05月11日 19:43:00";
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = df.parse(day);
System.out.println("当前日期:"+ date);
调用 SimpleDateFormat 对象的 parse() 方法时可能会出现转换异常,即 ParseException ,因此需要进行异常处理。 使用 Date 类时需要导入 java.util 包,使用 SimpleDateFormat 时需要导入 java.text包。
8 Calendar类的应用
Date 类最主要的作用就是获得当前时间,同时这个类里面也具有设置时间以及一些其他的功能,但是由于本身设计的问题,这些方法却遭到众多批评,不建议使用,更推荐使用 Calendar 类进行时间和日期的处理。 java.util.Calendar 类是一个抽象类,可以通过调用 getInstance() 静态方法获取一个 Calendar 对象,此对象已由当前日期时间初始化,即默认代表当前时间,如 Calendar c = Calendar.getInstance(); Calendar 类提供了 getTime() 方法,用来获取 Date 对象,完成 Calendar 和 Date 的转换,还可通过 getTimeInMillis() 方法,获取此 Calendar 的时间值,以毫秒为单位
Calendar calendar=Calendar.getInstance();
Date date=calendar.getTime();//获取时间
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(date));
System.out.println(calendar.getTimeInMillis());//毫秒为单位
9 使用Math类操作数据
Math 类位于 java.lang 包中,包含用于执行基本数学运算的方法, Math 类的所有方法都是静态方法,所以使用该类中的方法时,可以直接使用类名.方法名,如: Math.round(); 常用方法:
Math.round(11.5) // 12 11.5+0.5
Math.round(-11.5) //11 -11.5+0.5
10 HashMap和Hashtable的区别
1 两者最主要的区别在于Hashtable是线程安全,而HashMap则非线程安全。Hashtable的实现方法里面都添加了synchronized关键字来确保线程同步,因此相对而言HashMap性能会高一些,我们平时使用时若无特殊需求建议使用HashMap,在多线程环境下若使用HashMap需要使用Collections.synchronizedMap()方法来获取一个线程安全的集合(Collections.synchronizedMap()实现原理是Collections定义了一个SynchronizedMap的内部类,这个类实现了Map接口,在调用方法时使用synchronized来保证线程同步,当然了实际上操作的还是我们传入的HashMap实例,简单的说就是Collections.synchronizedMap()方法帮我们在操作HashMap时自动添加了synchronized来实现线程同步,类似的其它Collections.synchronizedXX方法也是类似原理。
2 HashMap可以使用null作为key,不过建议还是尽量避免这样使用。HashMap以null作为key时,总是存储在table数组的第一个节点上。而Hashtable则不允许null作为key。
3 HashMap继承了AbstractMap,HashTable继承Dictionary抽象类,两者均实现Map接口。
4 HashMap的初始容量为16,Hashtable初始容量为11,两者的填充因子默认都是0.75。
6 HashMap扩容时是当前容量翻倍即:capacity*2,Hashtable扩容时是容量翻倍+1即:capacity*2+1。
7 HashMap和Hashtable的底层实现都是数组+链表结构实现。
8 两者计算hash的方法不同:
Hashtable计算hash是直接使用key的hashcode对table数组的长度直接进行取模:
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
HashMap计算hash对key的hashcode进行了二次hash,以获得更好的散列值,然后对table数组长度取摸:
static int hash(int h) {
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}static int indexFor(int h, int length) {
return h & (length-1);
}
7.判断是否含有某个键
在HashMap 中,null 可以作为键,这样的键只有一个;可以有一个或多个键所对
应的值为null。当get()方法返回null 值时,既可以表示HashMap 中没有该键,也可
以表示该键所对应的值为null。因此,在HashMap 中不能用get()方法来判断HashM
ap 中是否存在某个键,而应该用containsKey()方法来判断。Hashtable 的键值都不能
为null,所以可以用get()方法来判断是否含有某个键。
HashMap和Hashtable都是实现Map接口的,但是:
1.HashMap允许键和值都是null的,而Hashtable不允许键和值为null
2.Hashtable是同步的,而HashMap不是。所以HashMap适用于单线程,而Hashtable适用于多线程
3.HashMap提供了可供应用迭代的键的集合,因此HashMap是快速失败的,而Hashtable是提供了对键的列举
11 .JVM的永久代中会发生垃圾回收么?
垃圾回收不会发生在永久代,如果永久代满了或者是超过了临界值,会触发完全垃圾回收(Full GC)。如果你仔细查看垃圾收集器的输出信息,就会发现永久代也是被回收的。这就是为什么正确的永久代大小对避免Full GC是非常重要的原因。请参考下Java8:从永久代到元数据区
(译者注:Java8中已经移除了永久代,新加了一个叫做元数据区的native内存区)
12 RMI体系结构分以下几层:
存根和骨架层(StubandSkeletonlayer):这一层对程序员是透明的,它主要负责拦截客户端发出的方法调用请求,然后把请求重定向给远程的RMI服务。
远程引用层(RemoteReferenceLayer):RMI体系结构的第二层用来解析客户端对服务端远程对象的引用。这一层解析并管理客户端对服务端远程对象的引用。连接是点到点的。
传输层(Transportlayer):这一层负责连接参与服务的两个JVM。这一层是建立在网络上机器间的TCP/IP连接之上的。它提供了基本的连接服务,还有一些防火墙穿透策略。
Naming类的bind()和rebind()方法有什么区别?
bind()方法负责把指定名称绑定给远程对象,rebind()方法负责把指定名称重新绑定到一个新的远程对象。如果那个名称已经绑定过了,先前的绑定会被替换掉。
JAVA IO和NIO的区别
java 常用集合list与Set、Map区别及适用场景总结
http://blog.csdn.net/qq_22118507/article/details/51576319
后续学习。。。。。
1 JDK中常用包及其类和功能
2 HashTable和HashMap的区别详解
HashTable和HashMap的区别详解 - CSDN博客
3 Object类
1,构造函数
2,hashCode和equale函数用来判断对象是否相同,
3,wait(),wait(long),wait(long,int),notify(),notifyAll()
4,toString()和getClass,
5,clone()
6,finalize()用于在垃圾回收
4 JVM运行内存
https://blog.csdn.net/jing18033612052/article/details/79187709
5 JAVA的原子性&可见性&有序性
https://blog.csdn.net/qq_33689414/article/details/73527438
6 JAVA继承详解
Java之中只允许多层继承,不允许多重继承,Java存在单继承局限
限制一:一个子类只能够继承一个父类,存在单继承局限
限制二:在一个子类继承的时候,实际上会继承父类之中的所有操作(属性、方法),但是需要注意的是,对于所有的非私有(no private)操作属于显式继承(可以直接利用对象操作),而所有的私有操作属于隐式继承(间接完成)
限制三:在继承关系之中,如果要实例化子类对象,会默认先调用父类构造,为父类之中的属性初始化,之后再调用子类构造,为子类之中的属性初始化,即:默认情况下,子类会找到父类之中的无参构造方法。
现在默认调用的是无参构造,而如果这个时候父类没有无参构造,则子类必须通过super()调用指定参数的构造方法
在任何的情况下,子类都逃不出父类构造的调用,很明显,super调用父类构造,这个语法和this()很相似:super调用父类构造时,一定要放在构造方法的首行上。
7 修饰符
2018 5 25
8 异常处理机制(throws和throw的区别)
try 块:用于捕获异常。其后可接零个或多个catch块,如果没有catch块,则必须跟一个finally块。
catch 块:用于处理try捕获到的异常。
finally 块:无论是否捕获或处理异常,finally块里的语句都会被执行。
当在try块或catch块中遇到return语句时,finally语句块将在方法返回之前被执行。在以下4种特殊情况下,finally块不会被执行:
1)在finally语句块中发生了异常。
2)在前面的代码中用了System.exit()退出程序。
3)程序所在的线程死亡。
4)关闭CPU。
图示try、catch、finally语句块的执行:
Throws抛出异常的规则:
1) 如果是不可查异常(unchecked exception),即Error、RuntimeException或它们的子类,那么可以不使用throws关键字来声明要抛出的异常,编译仍能顺利通过,但在运行时会被系统抛出。
2)必须声明方法可抛出的任何可查异常(checked exception)。即如果一个方法可能出现受可查异常,要么用try-catch语句捕获,要么用throws子句声明将它抛出,否则会导致编译错误
3)仅当抛出了异常,该方法的调用者才必须处理或者重新抛出该异常。当方法的调用者无力处理该异常的时候,应该继续抛出,而不是囫囵吞枣。
4)调用方法必须遵循任何可查异常的处理和声明规则。若覆盖一个方法,则不能声明与覆盖方法不同的异常。声明的任何异常必须是被覆盖方法所声明异常的同类或子类。
throw异常
throw总是出现在函数体中,用来抛出一个Throwable类型的异常。程序会在throw语句后立即终止,它后面的语句执行不到,然后在包含它的所有try块中(可能在上层调用函数中)从里向外寻找含有与其匹配的catch子句的try块。
我们知道,异常是异常类的实例对象,我们可以创建异常类的实例对象通过throw语句抛出。该语句的语法格式为:
throw new exceptionname;
例如抛出一个IOException类的异常对象:
throw new IOException;
要注意的是,throw 抛出的只能够是可抛出类Throwable 或者其子类的实例对象。下面的操作是错误的:
throw new String("exception");
这是因为String 不是Throwable 类的子类。
如果抛出了检查异常,则还应该在方法头部声明方法可能抛出的异常类型。该方法的调用者也必须检查处理抛出的异常。
如果所有方法都层层上抛获取的异常,最终JVM会进行处理,处理也很简单,就是打印异常消息和堆栈信息。如果抛出的是Error或RuntimeException,则该方法的调用者可选择处理该异常。
java中常见的异常
1. runtimeException子类:
1、 java.lang.ArrayIndexOutOfBoundsException
数组索引越界异常。当对数组的索引值为负数或大于等于数组大小时抛出。
2、java.lang.ArithmeticException
算术条件异常。譬如:整数除零等。
3、java.lang.NullPointerException
空指针异常。当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度、使用throw语句抛出null等等
4、java.lang.ClassNotFoundException
找不到类异常。当应用试图根据字符串形式的类名构造类,而在遍历CLASSPAH之后找不到对应名称的class文件时,抛出该异常。
5、java.lang.NegativeArraySizeException 数组长度为负异常
6、java.lang.ArrayStoreException数组中包含不兼容的值抛出的异常
7、java.lang.SecurityException安全性异常
8、java.lang.IllegalArgumentException非法参数异常
IOException:操作输入流和输出流时可能出现的异常。
EOFException 文件已结束异常
FileNotFoundException 文件未找到异常
ClassCastException 类型转换异常类
ArrayStoreException 数组中包含不兼容的值抛出的异常
SQLException 操作数据库异常类
NoSuchFieldException 字段未找到异常
NoSuchMethodException 方法未找到抛出的异常
NumberFormatException 字符串转换为数字抛出的异常
StringIndexOutOfBoundsException 字符串索引超出范围抛出的异常
IllegalAccessException 不允许访问某类异常
InstantiationException 当应用程序试图使用Class类中的newInstance()方法创建一个类的实例,而指定的类对象无法被实例化时,抛出该异常
9 JAVA中return的作用
return的常用作用有以下两种
一种是返回参数所用的关键字,假如一个有返回值的方法执行完了之后需要返回一个参数,示例:public string functionTest(){
String a = "abc";
return a;
}
那么这个方法被调用之后就会返回一个值为abc的字符串,string result = functionTest();
第二种用法是,代码执行到此处终止。
比如当代码执行到某个地方会出现几种结果,然后其中一种结果就不能执行后续代码,这时候在那里加上一个return就可以终止后面的代码执行。
10 Swing 继承框架图
Swing 是在AWT的基础上构建的一套新的图形界面系统,它提供了AWT 所能够提供的所有功能,并且用纯粹的Java代码对AWT 的功能进行了大幅度的扩充。swing是单线程的
AWT 是基于本地方法的C/C++程序,其运行速度比较快;Swing是基于AWT 的Java程序,其运行速度比较慢。
11 解决hashmap的冲突方法
1. 开放定址法:线性探测再散列、二次探测再散列、再随机探测再散列;
2. 再哈希法:换一种哈希函数;
3. 链地址法 :在数组中冲突元素后面拉一条链路,存储重复的元素;
4. 建立一个公共溢出区:其实就是建立一个表,存放那些冲突的元素。
什么时候会产生冲突
HashMap中调用 hashCode() 方法来计算hashCode。
由于在Java中两个不同的对象可能有一样的hashCode,所以不同的键可能有一样hashCode,从而导致冲突的产升。
HashMap底层是 数组和链表 的结合体。底层是一个线性数组结构,数组中的每一项又是一个链表。当新建一个HashMap的时候,就会初始化一个数组。数组是 Entry[] 数组,静态内部类。 E ntry就是数组中的元素,每个 Map.Entry 其实就是一个key-value对,它持有一个指向下一个元素的引用 next ,这就构成了链表。所以 很明显是链地址法。
具体过程:
当我们往HashMap中put元素的时候:当程序试图将一个key-value对放入HashMap中时,
1 . 程序首先根据该 key 的 hashCode() 返回值决定该 Entry 的存储位置;
2 . 若 Entry 的存储位置上为 null ,直接存储该对象;若不为空,两个 Entry 的 key 的 hashCode() 返回值相同,那它们的存储位置相同,
3 . 循环遍历链表,如果这两个 Entry 的 key 通过 equals 比较返回 true,新添加 Entry 的 value 将覆盖集合中原有 Entry 的 value,但key不会覆盖;如果这两个 Entry 的 key 通过 equals 比较返回 false,新添加的 Entry 将与集合中原有 Entry 形成 Entry 链,而且新添加的 Entry 位于 Entry 链的头部
3 未解决
JAVA中的ThreadLock https://www.cnblogs.com/chengxiao/p/6152824.html