------
本题要求键相同的两个对象间隔1秒进行输出,键不同的对象同时输出,另外即使键在字面上相同,即用equals进行内容比较一致,但由于每个键与空字符串进行相连,形
成了新的字符串,故即使是字符串常量,但也是两个不同的对象。
故第一步是能不能想到用键作为同步锁,第二步是用线程同步的集合进行键值的存储,第三步是当集合中存在equals相等的键时,要获取同一把锁。
另外一点值得注意的是ArrayList在进行迭代操作时,不能引用集合对象来操作集合中的元素,如在迭代时进行元素的增删。这是因为通过参看源代码,迭代器的hasNext方
法在返回值前会比较spectedCount与subCount的值(是在调用迭代器之前由集合增删方法所累加起来的值先赋给subCount,再赋给spectedCount,若在迭代器中再调用集合
中的增删方法,则累加的只有subCount,当两值不等时,hasNext方法会抛出异常)。
package cn.itcast;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;
public class CollectionElementsAsLock extends Thread{
private String key=null;
private String value=null;
private PrintKeyValue instance=null;
public CollectionElementsAsLock(String key,String key2,String value) {
// TODO Auto-generated constructor stub
instance=PrintKeyValue.getInstance();
this.key=key+key2;
this.value=value;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("begin:"+System.currentTimeMillis()/1000);
new CollectionElementsAsLock("1", "", "张三").start();
new CollectionElementsAsLock("1", "", "李四").start();
new CollectionElementsAsLock("2", "", "王五").start();
new CollectionElementsAsLock("3", "", "赵六").start();
}
@Override
public void run() {
// TODO Auto-generated method stub
instance.print(key, value);
}
}
class PrintKeyValue{
private PrintKeyValue(){};
private static PrintKeyValue instance=new PrintKeyValue();
public static PrintKeyValue getInstance(){
return instance;
}
// private Collection keys=new ArrayList();
private CopyOnWriteArrayList keys=new CopyOnWriteArrayList();
public void print(String key,String value){
String realKey=key;
if(!keys.contains(key)){
keys.add(key);
}else{
for(Iterator it=keys.iterator();it.hasNext();){
try {
Thread.sleep(20);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String tmp=it.next();
if(tmp.equals(realKey)){
realKey=tmp;
}
}
}
synchronized (realKey) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(key+":"+value+":"+System.currentTimeMillis()/1000);
}
}
}
AOP,面向方面编程,即为各个API类设置代理,在代理类中往往设置一个target(目标字段,即API类)和advice(Advice接口,用于功能扩展)两个字段,目标类可为一
般API类,通过实现Advice接口为API类附加其他功能,以代理对象进行返回。代理对象除了具有原API对象的方法之外,还附加了Advice实现类中的部分或全部功能,如性能测
试等。
代理的出现,可以按需要进行功能扩展,产生大量具备原目标对象功能的加强代理对象。
本例实现一个Bean工厂,可通过更改配置文件参数产生普通Bean对象和代理对象:
首先定义规则:
package cn.itcast;
public interface Advice {
void beforeMethod();
void afterMethod();
}
通过实现规则扩展功能:
package cn.itcast;
public class MyAdvice implements Advice {
long startTime=0;
@Override
public void beforeMethod() {
// TODO Auto-generated method stub
startTime=System.currentTimeMillis();
}
@Override
public void afterMethod() {
// TODO Auto-generated method stub
long endTime=System.currentTimeMillis();
System.out.println(endTime-startTime);
}
}
定义好了扩展功能后,就可以设置代理类:
package cn.itcast;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyFactoryBean {
private Object target;
private Advice advice;
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
public Advice getAdvice() {
return advice;
}
public void setAdvice(Advice advice) {
this.advice = advice;
}
public Object getProxy(){
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
advice.beforeMethod();
Object retVal=method.invoke(target, args);
advice.afterMethod();
return retVal;
}
});
}
}
Bean工厂:通过InputStream读取配置文件产生普通Bean或代理对象:
package cn.itcast;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class BeanFactory {
private InputStream ips;
private Properties props=null;
public BeanFactory(InputStream ips) {
super();
this.ips = ips;
props=new Properties();
try {
props.load(ips);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Object getBean(String key){
Object obj=null;
try {
obj=Class.forName(props.getProperty(key)).newInstance();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(obj instanceof ProxyFactoryBean){
ProxyFactoryBean pfb=(ProxyFactoryBean)obj;
Object retVal=null;
try {
pfb.setAdvice((Advice)Class.forName(props.getProperty(key+".advice")).newInstance());
pfb.setTarget(Class.forName(props.getProperty(key+".target")).newInstance());
retVal=pfb.getProxy();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return retVal;
}
return obj;
}
}
config.properties 配置文件如下:
#***=java.util.ArrayList
***=cn.itcast.ProxyFactoryBean
***.target=java.util.HashSet
***.advice=cn.itcast.MyAdvice
主函数进行测试:
package cn.itcast;
import java.util.Collection;
public class AOPFrameworkTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
BeanFactory beanFactory=new BeanFactory(AOPFrameworkTest.class.getResourceAsStream("config.properties"));
Object bean=beanFactory.getBean("***");
System.out.println(bean.getClass().getName());
Collection collction=(Collection)bean;
collction.add("a");
collction.add("b");
collction.add("c");
collction.add("b");
System.out.println(collction.size());
}
}