一.看ArrayList集合源码时,看到创建的底层数组是Object[]数组,而非范型数组,针对此问题查了些资料https://www.cnblogs.com/ixenos/p/5648519.html。
通过代码验证居然无法创建,百度之,原来JAVA不支持泛型数组,因为数组在创建的时候必须知道内部元素的类型,而JAVA是通过擦除法实现,运行时类型参数会被擦掉。
- 不能(直接)创建泛型数组
- 泛型数组实际的运行时对象数组只能是原始类型( T[]为Object[],Pair< T >[]为Pair[] ),而实际的运行时数组对象可能是T类型( 虽然运行时会擦除成原始类型 )
- 一般解决方案:(泛型数组包装器):使用ArrayList收集泛型数组对象的对象元素,如ArrayList< T >、ArrayList< Pair< String >>
将获得数组的行为,以及由泛型提供的编译期的类型安全。
二.java 延时队列DelayQueue -摘自:https://www.cnblogs.com/sunzhenchao/p/3515085.html
在学习Java 多线程并发开发过程中,了解到DelayQueue类的主要作用:是一个无界的BlockingQueue,用于放置实现了Delayed接口的对象,其中的对象只能在其到期时才能从队列中取走。这种队列是有序的,即队头对象的延迟到期时间最长。注意:不能将null元素放置到这种队列中。
Delayed,一种混合风格的接口,用来标记那些应该在给定延迟时间之后执行的对象。此接口的实现必须定义一个 compareTo 方法,该方法提供与此接口的 getDelay 方法一致的排序。
在网上也看到两个示例,但这两个示例个人在实际运行时均没有达到满足业务场景的效果,因而对其进行了修改,供大家参考讨论。
实际工作中,可应用在session超时管理,网络应答通讯协议的请求超时处理。
业务场景一:多考生考试
该场景来自于http://ideasforjava.iteye.com/blog/657384,模拟一个考试的日子,考试时间为120分钟,30分钟后才可交卷,当时间到了,或学生都交完卷了考试结束。
这个场景中几个点需要注意:
考试时间为120分钟,30分钟后才可交卷,初始化考生完成试卷时间最小应为30分钟
对于能够在120分钟内交卷的考生,如何实现这些考生交卷
对于120分钟内没有完成考试的考生,在120分钟考试时间到后需要让他们强制交卷
在所有的考生都交完卷后,需要将控制线程关闭
实现思想:用DelayQueue存储考生(Student类),每一个考生都有自己的名字和完成试卷的时间,Teacher线程对DelayQueue进行监控,收取完成试卷小于120分钟的学生的试卷。当考试时间120分钟到时,先关闭Teacher线程,然后强制DelayQueue中还存在的考生交卷。每一个考生交卷都会进行一次countDownLatch.countDown(),当countDownLatch.await()不再阻塞说明所有考生都交完卷了,而后结束考试。
注意⚠️
unit.convert(time - System.currentTimeMillis(), TimeUnit.MILLISECONDS)
第一个参数为数字,第二个参数为数字代表的时间单位,这里作为毫秒
执行convert后,返回unit当前的时间单位,此处是纳秒
如果第二个参数写成纳秒,
TimeUnit.NANOSECONDS,则这个转换函数转换前后数值相等,但是DelayQueue的take方法中
if (delay > 0) {
long tl = available.awaitNanos(delay);
}
等待的时间将缩短,上面的for循环重复执行将近原来的1000倍。这样会造成CPU空转,是load升高。
原型模式实际上就是实现Cloneable接口,重写clone()方法。
使用原型模式的优点:
● 性能优良
原型模式是在内存二进制流的拷贝,要比直接new一个对象性能好很多,特别是要在一个循环体内产生大量的对象时,原型模式可以更好地体现其优点。
● 逃避构造函数的约束
这既是它的优点也是缺点,直接在内存中拷贝,构造函数是不会执行的(参见13.4节)。
使用场景:
● 资源优化场景
类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
● 性能和安全要求的场景
通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
● 一个对象多个修改者的场景
一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
浅拷贝和深拷贝:
浅拷贝:Object类提供的方法clone只是拷贝本对象,其对象内部的数组、引用对象等都不拷贝,还是指向原生对象的内部元素地址,这种拷贝就叫做浅拷贝,其他的原始类型比如int、long、char、string(当做是原始类型)等都会被拷贝。
注意: 使用原型模式时,引用的成员变量必须满足两个条件才不会被拷贝:一是类的成员变量,而不是方法内变量;二是必须是一个可变的引用对象,而不是一个原始类型或不可变对象。
深拷贝:对私有的类变量进行独立的拷贝
如:thing.arrayList = (ArrayList)this.arrayList.clone();