您的位置:首页 > 编程语言 > Java开发

java-高新技术总结

2015-07-16 10:22 357 查看
1.反射和内省

反射:能动态修改Java代码,用于运行时检测和修改某个对象的结构及其行为

内省:内省是反射的一个子集,用于运行时检测某个对象的类型及其包含的属性

JavaBean:是一种特殊的Java类,主要用于传递数据信息。

使用案例:

package cn.itcast.day1;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;

public class IntroSpectorTest {

/**
* @param args
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
ReflectPoint pt1 = new ReflectPoint(3,5);

String propertyName = "x";
//"x"-->"X"-->"getX"-->MethodGetX-->
//读取对象的字段
Object retVal = getProperty(pt1, propertyName);
System.out.println(retVal);

Object value = 7;
//修改对象的字段
setProperties(pt1, propertyName, value);

System.out.println("beantils:"+BeanUtils.getProperty(pt1, "x").getClass().getName());
BeanUtils.setProperty(pt1, "x", "9");
System.out.println(pt1.getX());

/*//java7的新特性  ??????
Map map = {name:"zxx",age:18};
BeanUtils.setProperty(map, "na me", "lhm");
*/
BeanUtils.setProperty(pt1, "birthday.time", "111");
System.out.println(BeanUtils.getProperty(pt1, "birthday.time"));

PropertyUtils.setProperty(pt1, "x", 9);
System.out.println("x="+pt1.getX());
System.out.println(PropertyUtils.getProperty(pt1, "x").getClass().getName());

}
//直接利用属性描述器获取该字段的setter方法
private static void setProperties(Object pt1, String propertyName,
Object value) throws IntrospectionException,
IllegalAccessException, InvocationTargetException {
PropertyDescriptor pd2 = new PropertyDescriptor(propertyName,pt1.getClass());
Method methodSetX = pd2.getWriteMethod();
methodSetX.invoke(pt1,value);
}
//通过内省机制获取该类的Javabean,在通过Javabean获取该类的所有成员信息:属性描述器
private static Object getProperty(Object pt1, String propertyName)
throws IntrospectionException, IllegalAccessException,
InvocationTargetException {
/*PropertyDescriptor pd = new PropertyDescriptor(propertyName,pt1.getClass());
Method methodGetX = pd.getReadMethod();
Object retVal = methodGetX.invoke(pt1);*/
//获取pt1对象的beaninfo,它是用来传递数据的信息的
BeanInfo beanInfo =  Introspector.getBeanInfo(pt1.getClass());
//获取beaninfo中的所有属性描述器
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
Object retVal = null;
//遍历出想要的属性:propertyName
for(PropertyDescriptor pd : pds){
if(pd.getName().equals(propertyName))
{
//获取该属性的读取方法(getter)
Method methodGetX = pd.getReadMethod();
retVal = methodGetX.invoke(pt1);
break;
}
}
return retVal;
}

}


2.类加载器

类加载器:将类的字节码文件加载到内存中运行。

三大类加载器:

BootStrap: jre/lib/rt.jar

ExtClassLoader: jre/lib/ext/.*.jar ,文件

AppClassLoader(系统默认的类加载器):classPath下的类文件或目录

类加载器的委托机制:

每个类加载器加载类时,又先委托给其上级类加载器。--load方法

(如果类A中引用了类B,Java虚拟机将使用加载类A的类装载器来加载类B)

双亲委派机制:如果load方法找不到时,则用find方法找。好处:没有重名的类加载上

3.代理

静态代理:Thread采用了静态代理,Runnable是target,Thread是代理类,new Thread(Runnable target),将target交给代理类Thread执行。

动态代理:好处是可以在运行期动态生成出类的字节码,不需要为每个类配置静态代理的功能。

使用案例:

package cn.itcast.day3;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;

public class ProxyTest {

/**
* @param args
*/
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
//生成代理类
Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);

final ArrayList target = new ArrayList();
//根据target:ArrayList,和接口:Advice,创建一个代理类对象出来,该代理只关心target接口的方法,所以选择它的接口
Collection proxy3 = (Collection)getProxy(target,new MyAdvice());
proxy3.add("zxx");
proxy3.add("lhm");
proxy3.add("bxd");
System.out.println(proxy3.size());
System.out.println(proxy3.getClass().getName());
}
//根据target:ArrayList,和接口:Advice,创建一个代理类对象出来
private static Object getProxy(final Object target,final Advice advice) {
Object proxy3 = Proxy.newProxyInstance(
target.getClass().getClassLoader(),
/*new Class[]{Collection.class},*/
target.getClass().getInterfaces(), //获取target的接口,原因是代理类要调用target的方法,但是不关心具体内容,所以使用它的接口
new InvocationHandler(){

public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {

/*long beginTime = System.currentTimeMillis();
Object retVal = method.invoke(target, args);
long endTime = System.currentTimeMillis();
System.out.println(method.getName() + " running time of " + (endTime - beginTime));
return retVal;*/

advice.beforeMethod(method);//方法之前的操作
Object retVal = method.invoke(target, args);//调用目标类的方法
advice.afterMethod(method);//方法之后的操作
return retVal;

}
}
);
return proxy3;
}

}


4.线程篇

4.1 ThreadLocal

对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。

在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,

使用同步机制要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,程序设计和编写难度相对较大。

而ThreadLocal则从另一个角度来解决多线程的并发访问。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。

因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。

4.2 线程池

ExecutorService:Executors.
newCachedThreadPool(),Executors.
newFixedThreadPool(int nThreads),Executors.newSingleThreadExecutor()


作用:在线程池的编程模式下,任务是提交给整个线程池,而不是直接交给某个线程,线程池在拿到任务后,

它就在内部找有无空闲的线程,再把任务交给内部某个空闲的线程,这就是封装。记住,任务是提交给整个线程池,一个线程同时只能执行一个任务,但可以同时向一个线程池提交多个任务。

4.3 Callable&Future

作用:好比我同时种了几块地的麦子,然后就等待收割。收割时,则是那块先成熟了,则先去收割哪块麦子。

4.4 Lock&Condition
Lock:将“锁”的功能从“对象锁”中抽离出来,形成一个与对象无关,独立功能的锁。

condition:将对象中的等待,唤醒方法抽离出来,弄成一个condition条件的形式控制对象线程的等待,唤醒操作。

4.5 Semaphore

作用:Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目。

形式:
Semaphore(int permits),permits为固定的许可证数量,只有的到了“许可证”才可以执行任务,执行完任务后释放“许可证”


4.6 其他同步工具类

    CyclicBarrier :表示大家彼此等待,大家集合好后才开始出发,分散活动后又在指定地点集合碰面,这就好比整个公司的人员利用周末时间集体郊游一样,

           先各自从家出发到公司集合后,再同时出发到公园游玩,在指定地点集合后再同时开始就餐,…。

CountDownLatch: 犹如倒计时计数器,调用CountDownLatch对象的countDown方法就将计数器减1,当计数到达0时,则所有等待者或单个等待者开始执行。

这直接通过代码来说明CountDownLatch的作用,这样学员的理解效果更直接。 可以实现一个人(也可以是多个人)等待其他所有人都来通知他,

这犹如一个计划需要多个领导都签字后才能继续向下实施。还可以实现一个人通知多个人的效果,类似裁判一声口令,运动员同时开始奔跑。用这个功能做百米赛跑的游戏程序不错哦! Exchanger: 用于实现两个人之间的数据交换,每个人在完成一定的事务后想与对方交换数据,第一个先拿出数据的人将一直等待第二个人拿着数据到来时,才能彼此交换数据

4.7 可阻塞的队列

ArrayBlockingQueue 只有put方法和take方法才具有阻塞功能

BlockingQueue: 实现主要用于生产者-使用者队列

BlockingQueuez: 实现是线程安全的

作用:部分线程负责生产线,生产的产品数量固定,生产足够后,等待部分线程负责消费,然后生产线在补充生产,如此下去

class Producer implements Runnable {
private final BlockingQueue queue;
Producer(BlockingQueue q) { queue = q; }
public void run() {
try {
while(true) { queue.put(produce()); }
} catch (InterruptedException ex) { ... handle ...}
}
Object produce() { ... }
}

class Consumer implements Runnable {
private final BlockingQueue queue;
Consumer(BlockingQueue q) { queue = q; }
public void run() {
try {
while(true) { consume(queue.take()); }
} catch (InterruptedException ex) { ... handle ...}
}
void consume(Object x) { ... }
}

class Setup {
void main() {
BlockingQueue q = new SomeQueueImplementation();
Producer p = new Producer(q);
Consumer c1 = new Consumer(q);
Consumer c2 = new Consumer(q);
new Thread(p).start();
new Thread(c1).start();
new Thread(c2).start();
}
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: