1、UUID类
UUID是一个能够生成无重复字符串的程序类,这种程序类的主要功能是根据时间戳实现一个自动的无重复的字符串定义。
获取UUID对象:public static UUID randomUUID()
根据字符串获取UUID内容:public static UUID fromString(String name)
在对一些文件进行自动命名处理的情况下,UUID类型非常好用。
2、Optional类(JDK1.8)
这个类的功能是进行null相关的处理,类中的常用方法:
返回空数据:public static <T> Optional<T> empty()
获取数据:public T get()
保存数据,但是不允许出现null:public static <T> Optional<T> of(T value);(NullPointerException - if value is null)
保存数据且允许为空:public static <T> Optional<T> ofNullable(T value)
空的时候返回其他数据:public T orElse(T other)
运用示例:
package com.demo;
import java.util.Optional;
public class OptionDemo {
public static void main(String[] args) {
//IMessage2 temp = MessageUtil.getMessage().get() ; //数据不为空时获取数据
IMessage2 temp = MessageUtil.getMessage().orElse(null) ; //获取数据,如果数据为空则输出null
MessageUtil.useMessge(temp);
}
}
interface IMessage2 {
public String getContent() ;
}
class MessageImpl2 implements IMessage2 {
@Override
public String getContent() {
return "一只瓶子a";
}
}
class MessageUtil {
private MessageUtil() {} //构造方法私有化,外部不能实例化类对象
public static Optional<IMessage2> getMessage() {
return Optional.ofNullable(new MessageImpl2()); //保存数据且允许数据为空
}
public static void useMessge(IMessage2 msg) {
if(msg != null) {
System.out.println(msg.getContent()) ;
}
}
}
3、ThreadLocal类
当多个线程同时发送消息时(存、取消息)会互相有影响(数据覆盖、不同步),所以若要保持核心结构不改变,需要考虑到每个线程的独立操作问题,即可以多存放一个线程的标记,标记当前线程,这个时候就可以通过ThreadLocal类来存放数据。ThreadLocal类中的方法:
构造方法:创建ThreadLocal类对象:public ThreadLocal();
普通方法:
设置数据:public void set(T value)
获取数据:public T get()
删除数据:public void remove()
使用示例:
public class ThreadLocalDemo {
public static void main(String[] args) {
new Thread(()->{
IMessage imsg = new MessageImpl() ; //向上转型
imsg.setInfo("A消息");
Channel.setMessage(imsg); //向ThreadLocal中保存数据
Channel.send();
},"发送者A").start();
new Thread(()->{
IMessage imsg = new MessageImpl() ; //向上转型
imsg.setInfo("B消息");
Channel.setMessage(imsg);
Channel.send();
},"发送者B").start();
new Thread(()->{
IMessage imsg = new MessageImpl() ; //向上转型
imsg.setInfo("C消息");
Channel.setMessage(imsg);
Channel.send();
},"发送者C").start();
}
}
class Channel {
private static final ThreadLocal<IMessage> THREADLOCAL = new ThreadLocal<IMessage>() ;
private Channel() {}
public static void setMessage(IMessage msg) {
THREADLOCAL.set(msg); //向ThreadLocal中保存数据
}
public static void send() { //发送消息
System.out.println(Thread.currentThread().getName() + "发送消息:" + THREADLOCAL.get().getInfo());
}
}
interface IMessage { //消息接口-标准
public void setInfo(String info);
public String getInfo();
}
class MessageImpl implements IMessage { //消息实现类
private String info ;
public void setInfo(String info) {
this.info = info ;
}
public String getInfo() {
return this.info;
}
}
每一个线程通过ThreadLocal只允许保存一个数据。ThreadLocal类的工作原理:
①Thread类中有一个成员变量属于ThreadLocalMap类(一个定义在ThreadLocal类中的内部类),它是一个Map,他的key是ThreadLocal实例对象。
②当为ThreadLocal类的对象set值时,首先获得当前线程的ThreadLocalMap类属性,然后以ThreadLocal类的对象为key,设定value。get值时则类似。
③ThreadLocal变量的活动范围为某线程,是该线程独有的,对该变量的所有操作均由该线程完成!也就是说,ThreadLocal 不是用来解决共享对象的多线程访问的竞争问题的,因为ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。当线程终止后,这些值会作为垃圾回收。
4、定时调度
定时器的主要操作是进行定时任务的处理,是一种间隔触发的操作。
java.util.TimerTask类:实现定时任务处理;public abstract class TimerTask extends Object implements Runnable(启动一个单独的线程)
java.util.Timer类:启动任务,启动的方法:
任务启动:public void schedule(TimerTask task,long delay);延迟单位为毫秒
间隔触发:public void scheduleAtFixedRate(TimerTask task,long delay,long period)
使用示例:
import java.util.Timer;
import java.util.TimerTask;
class MyTask extends TimerTask { //任务主体
@Override
public void run() { //多线程的处理方法
System.out.println(Thread.currentThread().getName() + "执行任务,当前时间:" + System.currentTimeMillis());
}
}
public class TimerDemo {
public static void main(String[] args) {
Timer timer = new Timer() ; //定时任务
timer.scheduleAtFixedRate(new MyTask(),100,1000); //100毫秒后执行而后一秒执行一次
//timer.schedule(new MyTask(), 10000); //延迟时间设置为0表示立即启动
}
}
这种定时是由JDK最原始的方式提供的支持,但是使用较为复杂,无法具体地定时到某个日期。
5、Base64加密与解密
加密或者解密往往都有着一定的规则,从JDK1.8开始提供有一组新的加密处理操作类:Base64类,在这个类中有两个内部类:
Base64.Encoder:进行加密处理:public byte[] encode(byte[] src)
Base64.Decoder:进行解密处理:public byte[] decode(byte[] src)
String encMsg = new String(Base64.getEncoder().encode(msg.getBytes())) ; //数据加密
String oldMsg = new String(Base64.getDecoder().decode(encMsg)); //解密
Base64是一个公版的算法,所以如果直接对数据进行加密并不安全,最好的做法是使用盐值操作。
例如:
String amsg = "aaa" ; //需加密的数据
String salt = "bottle"; //盐值
String msg = "aaa" + "{" + salt + "}" ; //加密该处理后的数据
更为安全的加解密(自定义方法):
class StringUtil {
//加密
private static final String SALT = "bottle" ; //公共的盐值
private static final int REPEAT = 5 ; //加密次数
public static String encode(String str) {
byte data [] = temp.getBytes() ; //将字符串变为字符数组
String temp = "str" + "{" + SALT + "}" ;
for(int x = 0 ; x < REPEAT ; x ++) {
Base64.getEncoder().encode(data) ; //重复加密
}
return new String(data) ;
}
//解密
public static String decode(String str) {
byte data [] = str.getBytes() ;
for(int x = 0 ; x < REPEAT ; x ++) {
data = Base64.getDecodder().decode(data) ;
}
return new String(data).replaceAll("\\{[a-zA-Z0-9]\\}",""); //利用正则表达式替换掉盐值
}
}