Java笔记二
来源:互联网 发布:企业网站搜索优化 编辑:程序博客网 时间:2024/06/02 06:44
1.
Java集合框架之ConcurrentHashMap
HashTable容器在竞争激烈的并发环境下表现出效率低下的原因是:所有访问HashTable的线程都必须竞争同一把锁。那么假如容器里有多把锁,每一把锁用于锁容器其中一部分数据,那么当线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效的提高并发访问效率。这就是ConcurrentHashMap所使用的锁分段技术。首先,将数据分成一段一段的存储,然后给每一段数据分配一把锁,当一个线程占用锁访问其中一个数据段的时候,其他的数据也能被其他线程访问。
ConcurrentHashMap的结构:
由Segment数组结构和HashEntry数组结构组成。Segment是一种可重入锁ReentrantLock,在ConcurrentHashMap里扮演锁的角色。HashEntry则用于存储键值对数据。一个ConcurrentHashMap里包含一个Segment数组,一个Segment数组里包含一个HashEntry数组。Segment的结果和HashMap类似,是一种数组和链表结构,HashEntry是一种链表结构的元素。
一个Segment守护着一个HashEntry数组里的元素,当对HashEntry数组的数据进行修改时,必须首先获得它对应的Segment锁。
2.
java反射机制可以让我们在运行期检查类,接口,变量以及方法的信息。还可以让我们在运行期实例化对象,调用方法,通过调用get/set方法获取变量的值。
在想检查一个类的信息之前,首先需要获取类的Class对象。
在通常的观点中从对象的外部访问私有变量以及方法是不允许的,但是java反射机制可以做到这一点。
3.
Java有三个内建的Annotations。
@Deprecated
@Override
@SuppressWarnings
4.
利用java反射机制可以在运行期动态地创建接口的实现。java,lang.reflect.Proxy类就可以实现这一功能。可以通过使用Proxy.newProxyInstance()方法创建动态代理。newProxyInstance()方法有三个参数:
1.类加载器(ClassLoader)用来加载动态代理类
2.一个要实现的接口数组
3.一个InvocationHandler把所有方法的调用都转移到代理上。
InvocationHandler handler = new MyInvocationHandler(); MyInterface proxy = Proxy.newProxyInstance(MyInterface.class.getClassLoader(),new Class[]{ MyInterface.class },handler);执行完后,变量proxy包含一个MyInterface接口的动态实现。所有对proxy的调用都被转向到实现了InvocationHandler接口的Handler上。
所有对动态代理对象的方法调用都会被转向到了InvocationHandler接口的实现上。
5.
要提到并发,自然就要提到锁,通过使用锁,使得多线程的并发控制变得十分简单。但是付出的代价也很高,只有获取到锁的线程才能够执行代码,而其他线程必须挂起等待直到锁被释放,这期间它不能做任何事情。并且,在线程进行切换的过程中,即一个线程释放锁,另一个线程被调度获得锁并执行代码,也存在着很大的系统开销。然而人们对程序效率的追求并没有止步,程序的响应能不能更快一点、效率能不能更高一点等问题不断的激发着人们的热情。于是就产生了多种不同种类的锁,分别适用于在不同的场景下提高程序的并发效率。
乐观锁和悲观锁:
它们的区别在于悲观锁假设最坏的情况一定会发生,所以就在每次访问共享资源时都上锁。然而我们知道并不是所有的并发操作都会导致数据不一致,这就导致有些本来可以并发的线程由于不能获得锁而必须等待,从而降低了并发的效率。
乐观锁,就像它的名字一样,它以一种乐观的态度去访问共享数据,即它认为对共享数据的修改不会造成冲突,所以访问共享资源的时候并不加锁,如果它对共享资源的修改真的产生了冲突,那么它就会放弃这次修改,然后不管重试。
读写锁:
读写锁是一种锁分离技术,它把读锁和写锁分开,读锁可以被多个线程持有,这样读线程就可以并发,而写锁是互斥的,它只能被一个线程持有,并且写锁和读锁也互斥。
可重入锁:
synchronized就是可重入的,可重入锁就是说一个线程获取到锁后,在该线程内部又要递归的获取锁,如果锁不是可重入的,就会造成死锁,因为它不能获取到已经被自己保持的锁。可重入锁就是说一个线程内部递归的获取锁时,会使锁计数器加1,该线程没释放一个锁,锁的计数器就减1,当锁计数器为0时,锁就被完全释放。ReentrantLock
非阻塞同步算法:CompareAndSwap,乐观锁技术。
CompareAndSwap有三个操作数:内存值V,预期值A,新值B。当使用CompareAndSwap时,会先将预期值A与内存值V进行比较,如果相同,则把内存值V替换成新值B,如果不相同,则不进行替换,并返回内存中的实际值。这个语义可以解释为:我认为V的值应该为A,如果是,就把V的值替换成B,如果不是就不替换,并告诉我内存中的实际值。在JDK的原子类中都提供了这种基于乐观锁的CAS操作,而且concurrent包中的很多类也使用了这些原子类。在这些原子类中通过调用sun.misc.Unsafe里面的CAS算法,用CPU指令来实现无锁自增。
6.
内部类:
内部类的特点:
独立的class文件
同样需要编译
同样可以产生对象
静态内部类:
class Outer {
static class Inner {
//静态内部类不能访问到外部的成员,除非外部成员也是静态成员
}
}
静态内部创建对象:a.用外部类。b.导入内部类所在的包。c.用全限定名
C.成员内部类
class Outer {
class Inner{
//成员内部类可以访问到外部的成员,不能有静态变量和方法
}
}
成员内部类创建对象:Outer outer = new Outer();
Outer.Inner inner = ouer.new Inner();
D.局部内部类:只能在方法内部使用
class Outer {
void fd() {
class Inner{
//局部内部类
}
}
}
E.匿名内部类:
对于一个名为OuterClass的外部类和InnerClass的内部类,在编译成功后,会出现两个class文件:OuterClass.class和OuterClass$InnerClass.class
7.
HashSet类的特点:能够快速定位集合中的元素,集合中的元素无序。有了HashMap的实现,则HashSet的实现非常简单,只需要将Set中的元素作为Map的key值来保存即可。
8.
在Java中,能够表示数值的数据类型主要分为两类,一类是:float和double,,另一类是:byte,short,int和long。这些基本类型对应的封装类都继承了Number类。
public abstract class NumberDemo implements java.io.Serializable{ public abstract int intValue(); public abstract long longValue(); public abstract float floatValue(); public abstract double doubleValue(); public byte byteValue() { return (byte)intValue(); } public short shortValue() { return (short)intValue(); }}
几乎所有继承Number类的都对如上定义的几个方法进行了重新的实现。
private static class ByteCache { private ByteCache(){ } static final Byte cache[] = new Byte[-(-128)+127+1]; static { for (int i = 0; i < cache.length; i++) { cache[i] = new Byte((byte)(i-128)); } } } public static Byte valueOf(byte b) { final int offset = 128; return ByteCache.cache[(int)b+offset]; }
一个静态私有的内部类中定义了一个非常重要的Byte数组cache[]。这个cache在什么时候进行初始化呢?是在ByteCache静态类加载的时候,通过运行static静态块来完成的。那么这个静态内部类到底在什么时候加载呢?肯定是在valueOf()方法中调用的时候。
其实,数值类型中除了Float和Double类型外,Byte,Short,Integer,Long,Character,Boolean都实现了这种数值的共享,并且也都是-127~128区间值的缓存,而对于不在这个区间范围内的值,只能new一个对应的包装类型进行返回了
- JAVA学习笔记(二)
- JAVA学习笔记二
- Java笔记二:
- Java学习笔记二
- java学习笔记二
- JAVA学习笔记《二》
- JAVA笔记(二)
- Java培训笔记二
- Java学习笔记二
- Java学习笔记二
- JAVA笔记(二)
- java学习笔记(二)
- java学习笔记二
- java学习笔记二
- java学习笔记二
- Java学习笔记二
- java笔记(二)
- java笔记【二】
- 黑马程序员-(高新技术)类加载器
- linux shell scrip(脚本)编程简介------变量、特殊符号和表达式
- MySQL字符串函数
- 四月份总结:ACM竞赛到春假
- 搭建 maven 私服( 使用 Nexus )
- Java笔记二
- 关于java用jni调用 dll动态库Can't find dependent libraries错误的解决
- 《Cortex-CM3权威指南》——异常
- vector中存储的对象在clear时,会调用对象的析构函数
- C语言入门
- win8系统下u盘不显示怎么办
- C语言流程控制总结
- maven公共仓库
- Java基础——集合(上)之Collection