This commit is contained in:
yinkanglong
2023-10-21 09:48:50 +08:00
parent 5ef2c996cf
commit b2f069ee8d
555 changed files with 1886 additions and 506 deletions

View File

@@ -0,0 +1,25 @@
package cn.aofeng.demo.java.lang.instrument;
import java.lang.instrument.Instrumentation;
import org.apache.commons.lang.StringUtils;
import cn.aofeng.demo.util.LogUtil;
/**
* Instrument入口类。
*
* @author <a href="mailto:aofengblog@163.com">聂勇</a>
*/
public class FirstInstrumentation {
public static void premain(String options, Instrumentation ins) {
if (StringUtils.isBlank(options)) {
LogUtil.log("instrument without options");
} else {
LogUtil.log("instrument with options:%s", options);
}
ins.addTransformer(new FirstTransformer());
}
}

View File

@@ -0,0 +1,26 @@
/**
*
*/
package cn.aofeng.demo.java.lang.instrument;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import cn.aofeng.demo.util.LogUtil;
/**
* 只输出问候语不进行字节码修改的Class转换器。
*
* @author <a href="mailto:aofengblog@163.com">聂勇</a>
*/
public class FirstTransformer implements ClassFileTransformer {
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
LogUtil.log(">>> %s", className);
return null;
}
}

View File

@@ -0,0 +1,14 @@
package cn.aofeng.demo.java.lang.instrument;
/**
* Instrumentation启动类。 *
*
* @author <a href="mailto:aofengblog@163.com">聂勇</a>
*/
public class Hello {
public static void main(String[] args) {
// nothing
}
}

View File

@@ -0,0 +1,40 @@
# 一、Instrumentation入门
* [FirstTransformer.java](FirstTransformer.java) 处理字节码由类FirstInstrumentation执行
* [FirstInstrumentation.java](FirstInstrumentation.java) instrumentation入口类由javaagent载入执行
* [build.xml](build.xml) Ant脚本负责编译、打包和运行
在当前目录下执行命令:
```bash
ant
```
输出信息如下:
> [java] instrument with options:"Hello, Instrumentation"
> [java] >>> java/lang/invoke/MethodHandleImpl
> [java] >>> java/lang/invoke/MethodHandleImpl$1
> [java] >>> java/lang/invoke/MethodHandleImpl$2
> [java] >>> java/util/function/Function
> [java] >>> java/lang/invoke/MethodHandleImpl$3
> [java] >>> java/lang/invoke/MethodHandleImpl$4
> [java] >>> java/lang/ClassValue
> [java] >>> java/lang/ClassValue$Entry
> [java] >>> java/lang/ClassValue$Identity
> [java] >>> java/lang/ClassValue$Version
> [java] >>> java/lang/invoke/MemberName$Factory
> [java] >>> java/lang/invoke/MethodHandleStatics
> [java] >>> java/lang/invoke/MethodHandleStatics$1
> [java] >>> sun/misc/PostVMInitHook
> [java] >>> sun/usagetracker/UsageTrackerClient
> [java] >>> java/util/concurrent/atomic/AtomicBoolean
> [java] >>> sun/usagetracker/UsageTrackerClient$1
> [java] >>> sun/usagetracker/UsageTrackerClient$4
> [java] >>> sun/usagetracker/UsageTrackerClient$3
> [java] >>> java/io/FileOutputStream$1
> [java] >>> sun/launcher/LauncherHelper
> [java] >>> cn/aofeng/demo/java/lang/instrument/Hello
> [java] >>> sun/launcher/LauncherHelper$FXHelper
> [java] >>> java/lang/Class$MethodArray
> [java] >>> java/lang/Void
> [java] >>> java/lang/Shutdown
> [java] >>> java/lang/Shutdown$Lock

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="Instrumentation" default="run" basedir="../../../../../../../">
<property name="project.src.dir" value="${basedir}/src" />
<property name="project.lib.dir" value="${basedir}/lib" />
<property name="project.conf.dir" value="${basedir}/conf" />
<property name="project.target.dir" value="${basedir}/classes" />
<property name="project.dist.dir" value="${basedir}/dist" />
<path id="project.classpath">
<fileset dir="${project.lib.dir}">
<include name="*.jar" />
</fileset>
</path>
<target name="prepare">
<delete dir="${project.target.dir}" />
<mkdir dir="${project.target.dir}"/>
<copy todir="${project.target.dir}">
<fileset dir="${project.conf.dir}">
<include name="**/*.properties" />
<include name="**/*.xml" />
</fileset>
</copy>
<delete dir="${project.dist.dir}" />
<mkdir dir="${project.dist.dir}" />
</target>
<target name="compileWithJavac" depends="prepare">
<echo message="compile with javac" />
<javac destdir="${project.target.dir}" srcdir="${project.src.dir}" source="1.8" target="1.8"
encoding="UTF-8" debug="true" includeantruntime="false">
<classpath refid="project.classpath" />
</javac>
</target>
<target name="package" depends="compileWithJavac">
<jar destfile="${project.dist.dir}/hello.jar">
<fileset dir="${project.target.dir}">
<include name="cn/aofeng/demo/java/lang/instrument/*.class" />
</fileset>
<manifest>
<attribute name="Premain-Class" value="cn.aofeng.demo.java.lang.instrument.FirstInstrumentation" />
</manifest>
</jar>
</target>
<target name="run" depends="package">
<java classname="cn.aofeng.demo.java.lang.instrument.Hello" fork="true">
<classpath refid="project.classpath" />
<classpath location="${project.target.dir}" />
<jvmarg value="-javaagent:${project.dist.dir}/hello.jar=&quot;Hello, Instrumentation&quot;" />
</java>
</target>
</project>

View File

@@ -0,0 +1,143 @@
package cn.aofeng.demo.java.lang.reflect;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* 通过反射获取类的构造方法、字段、方法和注解等信息。
*
* @author <a href="mailto:aofengblog@163.com">聂勇</a>
*/
public class ClassAnalyze {
final static String PREFIX = "==========";
final static String SUFFIX = PREFIX;
private static void parseClass(Class<?> claz) {
// 注解
parseAnnotation(claz);
// 类
StringBuilder buffer = new StringBuilder(32)
.append( Modifier.toString(claz.getModifiers()) )
.append(' ')
.append(claz.getName());
log(buffer.toString());
}
private static void parseConstructor(Constructor<?> c) {
// 注解
parseAnnotation(c);
// 构造方法
StringBuilder buffer = new StringBuilder(32)
.append( parseMember(c) )
.append('(');
// 参数
Class<?>[] params = c.getParameterTypes();
for (int index = 0; index < params.length; index++) {
buffer.append(params[index].getName());
if (index!=params.length-1) {
buffer.append(", ");
}
}
buffer.append(')');
log(buffer.toString());
}
private static void parseMethod(Method method) {
// 注解
parseAnnotation(method);
// 方法
StringBuilder buffer = new StringBuilder(32)
.append( parseMember(method) )
.append('(');
// 参数
Class<?>[] params = method.getParameterTypes();
for (int index = 0; index < params.length; index++) {
buffer.append(params[index].getName());
if (index!=params.length-1) {
buffer.append(", ");
}
}
buffer.append(')');
log(buffer.toString());
}
private static void parseField(Field field) {
// 注解
parseAnnotation(field);
// 字段
StringBuilder buffer = parseMember(field);
log(buffer.toString());
}
/**
* 解析方法、字段或构造方法的信息。
* @param member 方法、字段或构造方法
* @return 修饰符和名称组成的字符串。
*/
private static StringBuilder parseMember(Member member) {
StringBuilder buffer = new StringBuilder()
.append(Modifier.toString(member.getModifiers()))
.append(' ')
.append(member.getName());
return buffer;
}
/**
* 解析注解信息。
*/
private static void parseAnnotation(AnnotatedElement ae) {
Annotation[] ans = ae.getDeclaredAnnotations();
for (Annotation annotation : ans) {
log(annotation.toString());
}
}
public static void log(String msg, Object... param) {
System.out.println( String.format(msg, param) );
}
public static void main(String[] args) throws ClassNotFoundException {
if (args.length != 1) {
log("无效的输入参数!");
log("示例:");
log("java cn.aofeng.demo.java.lang.reflect.ClassAnalyze java.util.HashMap");
}
Class<?> claz = Class.forName(args[0]);
log("%s类%s", PREFIX, SUFFIX);
parseClass(claz);
log("%s构造方法%s", PREFIX, SUFFIX);
Constructor<?>[] cs = claz.getDeclaredConstructors();
for (Constructor<?> constructor : cs) {
parseConstructor(constructor);
}
log("%s字段%s", PREFIX, SUFFIX);
Field[] fields = claz.getDeclaredFields();
for (Field field : fields) {
parseField(field);
}
log("%s方法%s", PREFIX, SUFFIX);
Method[] methods = claz.getDeclaredMethods();
for (Method method : methods) {
parseMethod(method);
}
}
}

View File

@@ -0,0 +1,36 @@
package cn.aofeng.demo.java.lang.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import cn.aofeng.demo.util.LogUtil;
/**
* 通过反射使用构造方法创建对象实例。
*
* @author <a href="mailto:aofengblog@163.com">聂勇</a>
*/
public class CreateInstance {
public static void main(String[] args) throws InstantiationException, IllegalAccessException,
NoSuchMethodException, SecurityException,
IllegalArgumentException, InvocationTargetException {
Class<Man> claz = Man.class;
// 调用默认的public构造方法
Man man = claz.newInstance();
LogUtil.log(man.toString());
// 调用带参数的protected构造方法
Constructor<Man> manC = claz.getDeclaredConstructor(String.class);
man = manC.newInstance("aofeng");
LogUtil.log(man.toString());
// 调用带参数的private构造方法
manC = claz.getDeclaredConstructor(String.class, int.class);
manC.setAccessible(true);
man = manC.newInstance("NieYong", 32);
LogUtil.log(man.toString());
}
}

View File

@@ -0,0 +1,37 @@
package cn.aofeng.demo.java.lang.reflect;
import java.lang.reflect.Field;
import static cn.aofeng.demo.util.LogUtil.log;
/**
* 通过反射设置字段。
*
* @author <a href="mailto:aofengblog@163.com">聂勇</a>
*/
public class InvokeField {
public static void main(String[] args) throws NoSuchFieldException,
SecurityException, IllegalArgumentException, IllegalAccessException {
Man man = new Man();
Class<?> claz = man.getClass();
log("==========设置public字段的值==========");
log("height的值:%d", man.height);
Field field = claz.getField("height");
field.setInt(man, 175);
log("height的值:%d", man.height);
log("==========设置private字段的值==========");
log("power的值:%d", man.getPower());
field = claz.getDeclaredField("power");
field.setAccessible(true);
field.setInt(man, 100);
log("power的值:%d", man.getPower());
log("==========获取private字段的值==========");
int power = field.getInt(man);
log("power的值:%d", power);
}
}

View File

@@ -0,0 +1,84 @@
package cn.aofeng.demo.java.lang.reflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import static cn.aofeng.demo.util.LogUtil.log;
/**
* 通过反射调用方法。
*
* @author <a href="mailto:aofengblog@163.com">聂勇</a>
*/
public class InvokeMethod {
/**
* 调用父类的方法。
*
* @param claz
* 类
* @param man
* 类对应的实例
*/
private static void invokeParentMethod(Class<Man> claz, Man man)
throws NoSuchMethodException, IllegalAccessException,
InvocationTargetException {
// 调用父类的public方法
Method method = claz.getMethod("setName", String.class);
method.invoke(man, "NieYong");
log(man.toString());
method = claz.getMethod("getName");
Object result = method.invoke(man);
log("name:%s", result);
// 调用父类的private方法
method = claz.getSuperclass().getDeclaredMethod("reset");
method.setAccessible(true);
result = method.invoke(man);
log(man.toString());
}
/**
* 调用自身的方法。
*
* @param claz
* 类
* @param man
* 类对应的实例
*/
private static void invokeSelfMethod(Class<Man> claz, Man man)
throws NoSuchMethodException, IllegalAccessException,
InvocationTargetException {
man.setName("XiaoMing");
// 调用自身的private方法
Method method = claz.getDeclaredMethod("setPower", int.class);
method.setAccessible(true);
method.invoke(man, 99);
log("power:%d", man.getPower());
// 调用自身的public方法
log("%s is marry:%s", man.getName(), (man.isMarry() ? "Yes" : "No"));
method = claz.getDeclaredMethod("setMarry", boolean.class);
method.invoke(man, true);
log("%s is marry:%s", man.getName(), (man.isMarry() ? "Yes" : "No"));
// 调用静态方法可将实例设置为null因为静态方法属于类
Man a = new Man("张三");
Man b = new Man("李四");
method = claz.getMethod("fight", Man.class, Man.class);
method.invoke(null, a, b); //
}
public static void main(String[] args) throws NoSuchMethodException,
SecurityException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException,
InstantiationException {
Class<Man> claz = Man.class;
Man man = claz.newInstance();
invokeParentMethod(claz, man);
invokeSelfMethod(claz, man);
}
}

View File

@@ -0,0 +1,63 @@
package cn.aofeng.demo.java.lang.reflect;
import cn.aofeng.demo.json.gson.Person;
import cn.aofeng.demo.util.LogUtil;
/**
* 男人。
*
* @author <a href="mailto:aofengblog@163.com">聂勇</a>
*/
public class Man extends Person {
private boolean marry;
private int power;
public int height;
public Man() {
super();
LogUtil.log("%s的默认构造方法被调用", Man.class.getName());
}
protected Man(String name) {
super(name, 0);
LogUtil.log("%s带name参数的构造方法被调用", Man.class.getName());
}
@SuppressWarnings("unused")
private Man(String name, int age) {
super(name, age);
LogUtil.log("%s带name和age参数的构造方法被调用", Man.class.getName());
}
public static void fight(Man a, Man b) {
String win = "unkown";
if (a.power > b.power) {
win = a.getName();
} else if (b.power > a.power) {
win = a.getName();
}
LogUtil.log("%s vs %s, fight result:%s", a.getName(), b.getName(), win);
}
public boolean isMarry() {
return marry;
}
public void setMarry(boolean marry) {
this.marry = marry;
}
public int getPower() {
return power;
}
@SuppressWarnings("unused")
private void setPower(int power) {
this.power = power;
}
}

View File

@@ -0,0 +1,74 @@
package cn.aofeng.demo.java.lang.serialization;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
/**
* 自定义序列化和反序列化。
*
* @author <a href="mailto:aofengblog@163.com">聂勇</a>
*/
public class Man implements Externalizable {
private String manName;
private int manAge;
private transient String password;
public Man() {
// nothing
}
public Man(String name, int age) {
this.manName = name;
this.manAge = age;
}
public Man(String name, int age, String password) {
this.manName = name;
this.manAge = age;
this.password = password;
}
public String getManName() {
return manName;
}
public void setManName(String manName) {
this.manName = manName;
}
public int getManAge() {
return manAge;
}
public void setManAge(int manAge) {
this.manAge = manAge;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(manName);
out.writeInt(manAge);
out.writeObject(password);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
manName = (String) in.readObject();
manAge = in.readInt();
password = (String) in.readObject();
}
}

View File

@@ -0,0 +1,79 @@
package cn.aofeng.demo.java.lang.serialization;
import java.io.Serializable;
/**
* 默认序列化和
*
* @author <a href="mailto:aofengblog@163.com">聂勇</a>
*/
public class People implements Serializable {
private static final long serialVersionUID = 6235620243018494633L;
private String name;
private int age;
private transient String address;
private static String sTestNormal;
private static transient String sTestTransient;
public People(String name) {
this.name = name;
}
public People(String name, int age) {
this.name = name;
this.age = age;
}
public People(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getsTestNormal() {
return sTestNormal;
}
public void setsTestNormal(String sTestNormal) {
People.sTestNormal = sTestNormal;
}
public String getsTestTransient() {
return sTestTransient;
}
public void setsTestTransient(String sTestTransient) {
People.sTestTransient = sTestTransient;
}
}

View File

@@ -0,0 +1,126 @@
package cn.aofeng.demo.java.lang.serialization;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 关键字 transient 测试。
*
* @author <a href="mailto:aofengblog@163.com">聂勇</a>
*/
public class TransientDemo {
private static Logger _logger = LoggerFactory.getLogger(TransientDemo.class);
private String _tempFileName = "TransientDemo";
/**
* 将对象序列化并保存到文件。
*
* @param obj 待序列化的对象
*/
public void save(Object obj) {
ObjectOutputStream outs = null;
try {
outs = new ObjectOutputStream(
new FileOutputStream( getTempFile(_tempFileName) ));
outs.writeObject(obj);
} catch (IOException e) {
_logger.error("save object to file occurs error", e);
} finally {
IOUtils.closeQuietly(outs);
}
}
/**
* 从文件读取内容并反序列化成对象。
*
* @return {@link People}对象。如果读取文件出错 或 对象类型转换失败返回null。
*/
public <T> T load() {
ObjectInputStream ins = null;
try {
ins = new ObjectInputStream(
new FileInputStream( getTempFile(_tempFileName)) );
return ((T) ins.readObject());
} catch (IOException e) {
_logger.error("load object from file occurs error", e);
} catch (ClassNotFoundException e) {
_logger.error("load object from file occurs error", e);
} finally {
IOUtils.closeQuietly(ins);
}
return null;
}
private File getTempFile(String filename) {
return new File(getTempDir(), filename);
}
private String getTempDir() {
return System.getProperty("java.io.tmpdir");
}
private void displayPeople(People people) {
if (null == people) {
return;
}
String template = "People[name:%s, age:%d, address:%s, sTestNormal:%s, sTestTransient:%s]";
System.out.println( String.format(template, people.getName(), people.getAge(),
people.getAddress(), people.getsTestNormal(), people.getsTestTransient()));
}
private void displayMan(Man man) {
if (null == man) {
return;
}
String template = "Man[manName:%s, manAge:%d, password:%s]";
System.out.println( String.format(template, man.getManName(), man.getManAge(), man.getPassword()) );
}
/**
* @param args
*/
public static void main(String[] args) {
System.out.println(">>> Serializable测试");
TransientDemo demo = new TransientDemo();
People people = new People("张三", 30, "中国广州");
people.setsTestNormal("normal-first");
people.setsTestTransient("transient-first");
System.out.println("序列化之前的对象信息:");
demo.displayPeople(people);
demo.save(people);
// 修改静态变量的值
people.setsTestNormal("normal-second");
people.setsTestTransient("transient-second");
People fromLoad = demo.load();
System.out.println("反序列化之后的对象信息:");
demo.displayPeople(fromLoad);
System.out.println("");
System.out.println(">>> Externalizable测试");
Man man = new Man("李四", 10, "假密码");
System.out.println("序列化之前的对象信息:");
demo.displayMan(man);
demo.save(man);
Man manFromLoadMan = demo.load();
System.out.println("反序列化之后的对象信息:");
demo.displayMan(manFromLoadMan);
}
}

View File

@@ -0,0 +1,20 @@
package cn.aofeng.demo.java.rmi;
/**
* 性别。
*
* @author <a href="mailto:aofengblog@163.com">聂勇</a>
*/
public class Gender {
/**
* 男。
*/
public final static char MALE = 'M';
/**
* 女。
*/
public final static char FEMALE = 'F';
}

View File

@@ -0,0 +1,60 @@
package cn.aofeng.demo.java.rmi;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
*
* @author <a href="mailto:aofengblog@163.com">聂勇</a>
*/
public class RmiClient {
private static Logger _logger = LoggerFactory.getLogger(RmiClient.class);
private static String assembleUrl(String hostUrl, String bindName) {
if (StringUtils.isBlank(hostUrl) || StringUtils.isBlank(bindName)) {
return null;
}
String host = hostUrl.endsWith("/") ? hostUrl.substring(0, hostUrl.length()-1) : hostUrl;
String name = bindName.startsWith("/") ? bindName.substring(1) : bindName;
return host + "/" + name;
}
/**
* @param args
* <ul>
* <li>[0]待连接的RMI主机。如rmi://192.168.56.102:9999</li>
* <li>[1]服务名称。如UserService</li>
* </ul>
*/
public static void main(String[] args) throws MalformedURLException, RemoteException, NotBoundException {
String host = args[0];
String serviceName = args[1];
String url = assembleUrl(host, serviceName);
UserService userService = (UserService) Naming.lookup(url);
String userId = "10000";
User user = userService.findById(userId);
_logger.info("身份证号为{}的用户信息{}", userId, user);
userId = "10001";
user = userService.findById(userId);
_logger.info("身份证号为{}的用户信息{}", userId, user);
String userName = "小明";
user = userService.findByName(userName);
_logger.info("姓名为{}的用户信息{}", userName, user);
userName = "张三";
user = userService.findByName(userName);
_logger.info("姓名为{}的用户信息{}", userName, user);
}
}

View File

@@ -0,0 +1,53 @@
package cn.aofeng.demo.java.rmi;
import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* RMI服务端。
*
* @author <a href="mailto:aofengblog@163.com">聂勇</a>
*/
public class RmiServer {
private static Logger _logger = LoggerFactory.getLogger(RmiServer.class);
public static Registry createRegistry(int port) {
Registry registry = null;
try {
registry = LocateRegistry.createRegistry(port);
} catch (RemoteException e) {
_logger.info( String.format("注册端口%s失败", port), e);
}
return registry;
}
/**
* @param args [0]:绑定端口
* @throws RemoteException
*/
public static void main(String[] args) throws RemoteException {
int port = Integer.parseInt(args[0]);
UserService userService = new UserServiceImpl();
Registry registry = createRegistry(port);
if (null == registry) {
System.exit(0);
}
String bindName = "UserService";
try {
registry.bind(bindName, userService);
} catch (AlreadyBoundException e) {
_logger.info("服务{}已经绑定过", bindName);
}
_logger.info("RMI Server started, listen port:{}", port);
}
}

View File

@@ -0,0 +1,170 @@
package cn.aofeng.demo.java.rmi;
import java.io.Serializable;
/**
* 用户信息。
*
* @author <a href="mailto:aofengblog@163.com">聂勇</a>
*/
public class User implements Serializable {
private static final long serialVersionUID = 7616705579045104892L;
/**
* 身份证号。
*/
private String id;
/**
* 姓名。
*/
private String name;
/**
* 性别M-男F-女。
*/
private char gender;
/**
* 出生日期。以毫秒存储。
*/
private long birthday;
/**
* 国家。
*/
private String country;
/**
* 省/州。
*/
private String province;
/**
* 市/区。
*/
private String city;
/**
* 街道详细地址。
*/
private String address;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
public long getBirthday() {
return birthday;
}
public void setBirthday(long birthday) {
this.birthday = birthday;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((country == null) ? 0 : country.hashCode());
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (country == null) {
if (other.country != null)
return false;
} else if (!country.equals(other.country))
return false;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public String toString() {
StringBuilder buffer = new StringBuilder(256)
.append("User [id=").append(id)
.append(", name=").append(name)
.append(", gender=").append(gender)
.append(", birthday=").append(birthday)
.append(", country=").append(country)
.append(", province=").append(province)
.append(", city=").append(city)
.append(", address=").append(address)
.append("]");
return buffer.toString();
}
}

View File

@@ -0,0 +1,19 @@
package cn.aofeng.demo.java.rmi;
import java.rmi.Remote;
import java.rmi.RemoteException;
/**
* 用户信息服务。
*
* @author <a href="mailto:aofengblog@163.com">聂勇</a>
*/
public interface UserService extends Remote {
public User findByName(String name) throws RemoteException;
public User findById(String id) throws RemoteException;
public boolean add(User user) throws RemoteException;
}

View File

@@ -0,0 +1,70 @@
package cn.aofeng.demo.java.rmi;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import org.apache.commons.lang.StringUtils;
/**
* 用户信息服务。
*
* @author <a href="mailto:aofengblog@163.com">聂勇</a>
*/
public class UserServiceImpl extends UnicastRemoteObject implements UserService {
public UserServiceImpl() throws RemoteException {
super();
}
private static final long serialVersionUID = -9134952963637302483L;
@Override
public User findByName(String name) throws RemoteException {
if (StringUtils.isBlank(name)) {
return null;
}
if ("小明".equals(name)) {
return createUser("10000", "小明", Gender.MALE);
}
return null;
}
@Override
public User findById(String id) throws RemoteException {
if (StringUtils.isBlank(id)) {
return null;
}
if ("10000".equals(id)) {
return createUser("10000", "小丽", Gender.FEMALE);
}
return null;
}
@Override
public boolean add(User user) throws RemoteException {
if (null == user || StringUtils.isBlank(user.getId()) || StringUtils.isBlank(user.getName())) {
return false;
}
return true;
}
private User createUser(String id, String name, char gender) {
User user = new User();
user.setId(id);
user.setName(name);
user.setGender(gender);
user.setBirthday(System.currentTimeMillis());
user.setCountry("中国");
user.setProvince("广东");
user.setCity("广州");
user.setAddress("xxx区xxx街道xxx号");
return user;
}
}

View File

@@ -0,0 +1,78 @@
package cn.aofeng.demo.java.util.concurret;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import cn.aofeng.demo.util.DateUtil;
/**
* {@link ScheduledExecutorService}的使用示例:<br>
* 定时任务1执行过程中会抛出异常。<br>
* 定时任务2执行过程中不会抛出异常。<br>
* <br>
* 目的检测java.util.concurrent.ScheduledExecutorService在执行定时任务的过程中任务内抛出异常没有捕捉时在下一次执行时间到来时是否可以正常执行。<br>
* 测试的JDK版本1.6.xx。<br>
* 结果通过相比java.util.Timer完善地解决了定时任务抛异常的问题。
*
* @author <a href="mailto:aofengblog@163.com">聂勇</a>
*/
public class ScheduledExecutorServiceDemo {
public static void main(String[] args) {
ScheduledExecutorService timer = Executors.newScheduledThreadPool(2);
long delay = computeDelay();
timer.schedule(new ThrowExceptionTask(timer), delay, TimeUnit.MILLISECONDS);
timer.schedule(new NotThrowExceptionTask(timer), delay, TimeUnit.MILLISECONDS);
System.out.println("主线程的功能执行完毕");
}
private static long computeDelay() {
Date now = new Date();
Date nextMinute = DateUtil.getNextMinute();
long delay = nextMinute.getTime() - now.getTime();
return delay;
}
static class ThrowExceptionTask implements Runnable {
private ScheduledExecutorService _timer;
public ThrowExceptionTask(ScheduledExecutorService timer) {
this._timer = timer;
}
@Override
public void run() {
try {
System.out.println("任务名:ThrowExceptionTask, 当前时间:"+DateUtil.getCurrentTime());
throw new IllegalArgumentException();
} finally {
_timer.schedule(new ThrowExceptionTask(_timer), computeDelay(), TimeUnit.MILLISECONDS);
}
}
} // end of ThrowExceptionTask
static class NotThrowExceptionTask implements Runnable {
private ScheduledExecutorService _timer;
public NotThrowExceptionTask(ScheduledExecutorService timer) {
this._timer = timer;
}
@Override
public void run() {
try {
System.out.println("任务名:NotThrowExceptionTask, 当前时间:"+DateUtil.getCurrentTime());
} finally {
_timer.schedule(new NotThrowExceptionTask(_timer), computeDelay(), TimeUnit.MILLISECONDS);
}
}
} // end of NotThrowExceptionTask
}

View File

@@ -0,0 +1,103 @@
package cn.aofeng.demo.java.util.forkjoin;
import java.util.Arrays;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.TimeUnit;
/**
* Fork/Join练习。
*
* @author <a href="mailto:aofengblog@163.com">聂勇</a>
*/
public class HelloForkJoin extends RecursiveTask<Long> {
private static final long serialVersionUID = -2386438994963147457L;
private int[] _intArray;
private int _threshold = 10;
private long _result = 0;
public HelloForkJoin(int[] intArray) {
this._intArray = intArray;
}
@Override
protected Long compute() {
if (null == _intArray || _intArray.length <= 0) {
return 0L;
}
if (_intArray.length <= _threshold) { // 如果数组长度小于等于指定的值,执行累加操作
for (int item : _intArray) {
_result += item;
}
System.out.println( String.format("线程:%s累加数组%s中的值结果%d", Thread.currentThread(), Arrays.toString(_intArray), _result) );
} else { // 如果数组长度大于指定的值,做任务分解
int[] temp = new int[_threshold];
System.arraycopy(_intArray, 0, temp, 0, _threshold);
HelloForkJoin subTask1 = new HelloForkJoin(temp);
subTask1.fork();
if (_intArray.length - _threshold > 0) {
int remain[] = new int[_intArray.length - _threshold];
System.arraycopy(_intArray, _threshold, remain, 0, remain.length);
HelloForkJoin task = new HelloForkJoin(remain);
task.fork();
_result += task.join();
}
_result += subTask1.join();
return _result;
}
return _result;
}
public static void main(String[] args) throws InterruptedException {
int count = 10000;
serialCompute(count);
parallelCompute(count);
}
/**
* 使用fork/join并行计算数字累加。
*
* @param count 数字个数从1开始
* @throws InterruptedException
*/
private static void parallelCompute(int count)
throws InterruptedException {
int[] numbers = new int[count];
for (int i = 0; i < count; i++) {
numbers[i] = i+1;
}
ForkJoinPool pool = new ForkJoinPool(4);
HelloForkJoin task = new HelloForkJoin(numbers);
long startTime = System.currentTimeMillis();
pool.submit(task);
pool.shutdown();
pool.awaitTermination(10, TimeUnit.SECONDS);
System.out.println( String.format("并行计算结果:%d耗时%d毫秒", task._result, System.currentTimeMillis()-startTime) );
}
/**
* 使用for循环串行计算数字累加。
*
* @param count 数字个数从1开始
*/
private static void serialCompute(int count) {
long startTime = System.currentTimeMillis();
int sum = 0;
for (int i = 0; i < count; i++) {
sum += (i+1);
}
System.out.println( String.format("串行计算结果:%d耗时%d毫秒", sum, System.currentTimeMillis()-startTime) );
}
}

View File

@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<class-diagram version="1.1.6" icons="true" always-add-relationships="false" generalizations="true" realizations="true"
associations="true" dependencies="false" nesting-relationships="true">
<interface id="1" language="java" name="java.util.concurrent.Future" project="JavaDemo"
file="/devdata/java/jdk/jdk1.7.0_60/jre/lib/rt.jar" binary="true" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="334" y="85"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" accessors="true"
visibility="true">
<attributes public="false" package="true" protected="false" private="false" static="false"/>
<operations public="true" package="true" protected="false" private="false" static="false"/>
</display>
</interface>
<class id="2" language="java" name="java.util.concurrent.FutureTask" project="JavaDemo"
file="/devdata/java/jdk/jdk1.7.0_60/jre/lib/rt.jar" binary="true" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="521" y="477"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" accessors="true"
visibility="true">
<attributes public="false" package="true" protected="false" private="false" static="false"/>
<operations public="true" package="true" protected="false" private="false" static="false"/>
</display>
</class>
<interface id="3" language="java" name="java.util.concurrent.RunnableFuture" project="JavaDemo"
file="/devdata/java/jdk/jdk1.7.0_60/jre/lib/rt.jar" binary="true" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="521" y="280"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" accessors="true"
visibility="true">
<attributes public="false" package="true" protected="false" private="false" static="false"/>
<operations public="true" package="true" protected="false" private="false" static="false"/>
</display>
</interface>
<interface id="4" language="java" name="java.util.concurrent.RunnableScheduledFuture" project="JavaDemo"
file="/devdata/java/jdk/jdk1.7.0_60/jre/lib/rt.jar" binary="true" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="130" y="410"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" accessors="true"
visibility="true">
<attributes public="false" package="true" protected="false" private="false" static="false"/>
<operations public="true" package="true" protected="false" private="false" static="false"/>
</display>
</interface>
<interface id="5" language="java" name="java.util.concurrent.ScheduledFuture" project="JavaDemo"
file="/devdata/java/jdk/jdk1.7.0_60/jre/lib/rt.jar" binary="true" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="131" y="272"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" accessors="true"
visibility="true">
<attributes public="false" package="true" protected="false" private="false" static="false"/>
<operations public="true" package="true" protected="false" private="false" static="false"/>
</display>
</interface>
<interface id="6" language="java" name="java.util.concurrent.Delayed" project="JavaDemo"
file="/devdata/java/jdk/jdk1.7.0_60/jre/lib/rt.jar" binary="true" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="131" y="119"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" accessors="true"
visibility="true">
<attributes public="false" package="true" protected="false" private="false" static="false"/>
<operations public="true" package="true" protected="false" private="false" static="false"/>
</display>
</interface>
<interface id="7" language="java" name="java.lang.Runnable" project="JavaDemo"
file="/devdata/java/jdk/jdk1.7.0_60/jre/lib/rt.jar" binary="true" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="521" y="119"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" accessors="true"
visibility="true">
<attributes public="false" package="true" protected="false" private="false" static="false"/>
<operations public="true" package="true" protected="false" private="false" static="false"/>
</display>
</interface>
<generalization id="8">
<end type="SOURCE" refId="4"/>
<end type="TARGET" refId="5"/>
</generalization>
<generalization id="9">
<end type="SOURCE" refId="3"/>
<end type="TARGET" refId="7"/>
</generalization>
<generalization id="10">
<end type="SOURCE" refId="4"/>
<end type="TARGET" refId="3"/>
</generalization>
<generalization id="11">
<end type="SOURCE" refId="5"/>
<end type="TARGET" refId="6"/>
</generalization>
<generalization id="12">
<end type="SOURCE" refId="5"/>
<end type="TARGET" refId="1"/>
</generalization>
<generalization id="13">
<end type="SOURCE" refId="3"/>
<end type="TARGET" refId="1"/>
</generalization>
<realization id="14">
<end type="SOURCE" refId="2"/>
<end type="TARGET" refId="3"/>
</realization>
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
accessors="true" visibility="true">
<attributes public="false" package="true" protected="false" private="false" static="false"/>
<operations public="true" package="true" protected="false" private="false" static="false"/>
</classifier-display>
<association-display labels="true" multiplicity="true"/>
</class-diagram>

View File

@@ -0,0 +1,106 @@
package cn.aofeng.demo.java.util.future;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.apache.log4j.Logger;
/**
* Future、Callable练习。
*
* @author <a href="mailto:aofengblog@163.com">聂勇</a>
*/
public class HelloFuture {
private static Logger _logger = Logger.getLogger(HelloFuture.class);
/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
executeSingleTask();
executeBatchTask();
}
/**
* 执行单个异步任务:<br>
* 1、用submit方法向线程池提交一个任务。<br>
* 2、获取结果时指定了超时时间。<br><br>
* 结果超时后调用者收到TimeoutException但实际上任务还在继续执行。
* @throws InterruptedException
*/
private static void executeSingleTask() throws InterruptedException {
ExecutorService threadpool = Executors.newFixedThreadPool(6);
try {
Future<Integer> f = threadpool.submit(createCallable(5 * 1000));
Object result = f.get(3, TimeUnit.SECONDS);
System.out.println("单个任务的执行结果:"+result);
} catch (Exception e) {
_logger.error("线程执行任务时出错", e);
} finally {
threadpool.shutdown();
threadpool.awaitTermination(10, TimeUnit.SECONDS);
}
}
/**
* 执行多个异步任务:<br>
* 1、用invokeAll方法向线程池提交多个任务并指定了执行的超时时间。<br><br>
* 结果超时后未执行完成的任务被取消在调用Future的get方法时取消的任务会抛出CancellationException执行完成的任务可获得结果。
* @throws InterruptedException
*/
private static void executeBatchTask() throws InterruptedException {
ExecutorService threadpool = Executors.newFixedThreadPool(6);
List<Callable<Integer>> tasks = new ArrayList<Callable<Integer>>();
tasks.add(createCallable(2000));
tasks.add(createCallable(5000));
tasks.add(createCallable(2500));
long startTime = System.currentTimeMillis();
try {
List<Future<Integer>> fs = threadpool.invokeAll(tasks, 3, TimeUnit.SECONDS);
int result = 0;
for (Future<Integer> f : fs) {
try{
result += f.get();
} catch(CancellationException ce) {
// nothing
}
}
System.out.println("执行三个任务共耗时:" + (System.currentTimeMillis() - startTime) + "毫秒");
System.out.println("三个任务的执行结果汇总:"+result);
} catch (Exception e) {
_logger.error("线程执行任务时出错", e);
} finally {
threadpool.shutdown();
threadpool.awaitTermination(10, TimeUnit.SECONDS);
}
}
/**
* 创建需要长时间执行的任务模拟对象。
* @param sleepTimes 线程休眠时间(单位:毫秒)
* @return {@link Callable}对象
*/
private static Callable<Integer> createCallable(final int sleepTimes) {
Callable<Integer> c = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
Thread.sleep(sleepTimes);
System.out.println(Thread.currentThread().getName() + ": I'm working");
return 9;
}
};
return c;
}
}

View File

@@ -0,0 +1,139 @@
<?xml version="1.0" encoding="UTF-8"?>
<class-diagram version="1.1.6" icons="true" always-add-relationships="false" generalizations="true" realizations="true"
associations="true" dependencies="false" nesting-relationships="true">
<interface id="1" language="java" name="java.util.Map" project="JavaDemo"
file="/devdata/java/jdk/jdk1.6.0_45/jre/lib/rt.jar" binary="true" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="417" y="179"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" accessors="true"
visibility="true">
<attributes public="false" package="false" protected="false" private="false" static="true"/>
<operations public="true" package="true" protected="false" private="false" static="true"/>
</display>
</interface>
<class id="2" language="java" name="java.util.AbstractMap" project="JavaDemo"
file="/devdata/java/jdk/jdk1.6.0_45/jre/lib/rt.jar" binary="true" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="417" y="423"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" accessors="true"
visibility="true">
<attributes public="false" package="false" protected="false" private="false" static="true"/>
<operations public="false" package="false" protected="false" private="false" static="true"/>
</display>
</class>
<class id="3" language="java" name="java.util.HashMap" project="JavaDemo"
file="/devdata/java/jdk/jdk1.6.0_45/jre/lib/rt.jar" binary="true" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="824" y="422"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" accessors="true"
visibility="true">
<attributes public="false" package="false" protected="false" private="false" static="false"/>
<operations public="false" package="false" protected="false" private="false" static="true"/>
</display>
</class>
<class id="4" language="java" name="java.util.Hashtable" project="JavaDemo"
file="/devdata/java/jdk/jdk1.6.0_45/jre/lib/rt.jar" binary="true" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="152" y="312"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" accessors="true"
visibility="true">
<attributes public="false" package="false" protected="false" private="false" static="true"/>
<operations public="false" package="false" protected="false" private="false" static="true"/>
</display>
</class>
<class id="5" language="java" name="java.util.IdentityHashMap" project="JavaDemo"
file="/devdata/java/jdk/jdk1.6.0_45/jre/lib/rt.jar" binary="true" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="206" y="423"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" accessors="true"
visibility="true">
<attributes public="false" package="false" protected="false" private="false" static="true"/>
<operations public="false" package="false" protected="false" private="false" static="true"/>
</display>
</class>
<class id="6" language="java" name="java.util.LinkedHashMap" project="JavaDemo"
file="/devdata/java/jdk/jdk1.6.0_45/jre/lib/rt.jar" binary="true" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="824" y="283"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" accessors="true"
visibility="true">
<attributes public="false" package="false" protected="false" private="false" static="true"/>
<operations public="false" package="false" protected="false" private="false" static="true"/>
</display>
</class>
<class id="7" language="java" name="java.util.EnumMap" project="JavaDemo"
file="/devdata/java/jdk/jdk1.6.0_45/jre/lib/rt.jar" binary="true" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="329" y="528"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" accessors="true"
visibility="true">
<attributes public="false" package="false" protected="false" private="false" static="true"/>
<operations public="false" package="false" protected="false" private="false" static="true"/>
</display>
</class>
<class id="8" language="java" name="java.util.TreeMap" project="JavaDemo"
file="/devdata/java/jdk/jdk1.6.0_45/jre/lib/rt.jar" binary="true" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="499" y="526"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" accessors="true"
visibility="true">
<attributes public="false" package="false" protected="false" private="false" static="true"/>
<operations public="false" package="false" protected="false" private="false" static="true"/>
</display>
</class>
<class id="9" language="java" name="java.util.WeakHashMap" project="JavaDemo"
file="/devdata/java/jdk/jdk1.6.0_45/jre/lib/rt.jar" binary="true" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="609" y="374"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" accessors="true"
visibility="true">
<attributes public="false" package="false" protected="false" private="false" static="true"/>
<operations public="false" package="false" protected="false" private="false" static="true"/>
</display>
</class>
<generalization id="10">
<end type="SOURCE" refId="9"/>
<end type="TARGET" refId="2"/>
</generalization>
<generalization id="11">
<end type="SOURCE" refId="8"/>
<end type="TARGET" refId="2"/>
</generalization>
<realization id="12">
<end type="SOURCE" refId="5"/>
<end type="TARGET" refId="1"/>
</realization>
<generalization id="13">
<end type="SOURCE" refId="3"/>
<end type="TARGET" refId="2"/>
</generalization>
<realization id="14">
<end type="SOURCE" refId="4"/>
<end type="TARGET" refId="1"/>
</realization>
<realization id="15">
<end type="SOURCE" refId="2"/>
<end type="TARGET" refId="1"/>
</realization>
<realization id="16">
<end type="SOURCE" refId="3"/>
<end type="TARGET" refId="1"/>
</realization>
<generalization id="17">
<end type="SOURCE" refId="7"/>
<end type="TARGET" refId="2"/>
</generalization>
<realization id="18">
<end type="SOURCE" refId="9"/>
<end type="TARGET" refId="1"/>
</realization>
<generalization id="19">
<end type="SOURCE" refId="6"/>
<end type="TARGET" refId="3"/>
</generalization>
<generalization id="20">
<end type="SOURCE" refId="5"/>
<end type="TARGET" refId="2"/>
</generalization>
<realization id="21">
<end type="SOURCE" refId="6"/>
<end type="TARGET" refId="1"/>
</realization>
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
accessors="true" visibility="true">
<attributes public="true" package="true" protected="false" private="false" static="true"/>
<operations public="true" package="true" protected="false" private="false" static="true"/>
</classifier-display>
<association-display labels="true" multiplicity="true"/>
</class-diagram>

View File

@@ -0,0 +1,47 @@
package cn.aofeng.demo.java.util.timer;
import java.util.Timer;
import java.util.TimerTask;
import cn.aofeng.demo.util.DateUtil;
/**
* {@link Timer}的使用示例:<br>
* 定时任务1执行过程中会抛出异常。<br>
* 定时任务2执行过程中不会抛出异常。<br>
* <br>
* 目的检测java.util.Timer在执行定时任务的过程中任务内抛出异常没有捕捉时在下一次执行时间到来时是否可以正常执行。<br>
* 测试的JDK版本1.6.xx。<br>
* 结果不通过定时任务抛出异常时整个Timer中止其他定时任务也中止。
*
* @author <a href="mailto:aofengblog@163.com">聂勇</a>
*/
public class TimerDemo {
public static void main(String[] args) {
Timer timer = new Timer("aofeng-timer-demo");
timer.schedule(new ThrowExceptionTask(), DateUtil.getNextMinute(), 60*1000);
timer.schedule(new NotThrowExceptionTask(), DateUtil.getNextMinute(), 60*1000);
}
static class ThrowExceptionTask extends TimerTask {
@Override
public void run() {
System.out.println("任务名:ThrowExceptionTask, 当前时间:"+DateUtil.getCurrentTime());
throw new IllegalArgumentException();
}
} // end of ThrowExceptionTask
static class NotThrowExceptionTask extends TimerTask {
@Override
public void run() {
System.out.println("任务名:NotThrowExceptionTask, 当前时间:"+DateUtil.getCurrentTime());
}
} // end of NotThrowExceptionTask
}