UUID
-
一般在获取UUID的时候往往都是随机生成,通过以下方式获取:
// 获取UUID对象 public static UUID randomUUID(); // 根据字符串获取UUID内容 public static UUID fromString(String name);
-
在对一些文件进行自动命名处理的情况下,UUID非常好用
Optional
-
Optional类的功能是进行null的相关处理
-
该类提供如下的操作方法:
// 返回空数据 public static <T> Optional<T> empty(); // 获取数据 public T get(); // 保存数据,但是不允许出现null public static <T> Optional<T> of(T value); // 如果在保存数据的时候存在null,则会抛出NullPointerException异常 // 保存数据,允许为空 public static <T> Optional<T> ofNullable(T value); // 数据为空的时候返回其他数据 public T orElse(T other);
-
在所有引用数据类型的操作处理之中,null是一个很重要的技术问题,所以JDK1.8后提供Optional类提供帮助,Optional在日后进行项目开发中使用次数会很多
ThreadLocal类
-
这个类是在开发中特别重要的类,主要解决核心资源与多线程并发访问的处理情况
-
来看一个单线程的程序处理:
class Channel { private static Message message; public static void setMessage(Message m) { message = m; } public static void send() { System.out.println("【消息发送】" + message.getInfo()); } } class Message { private String info; public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } } public class ThreadLocalDemo { public static void main(String[] args) { Message msg = new Message(); msg.setInfo("周海林真帅!"); Channel.setMessage(msg); Channel.send(); } }
-
多线程的影响:
class Channel { private static Message message; public static void setMessage(Message m) { message = m; } public static void send() { System.out.println("【" + Thread.currentThread().getName() + "消息发送】" + message.getInfo()); } } class Message { private String info; public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } } public class ThreadLocalDemo { public static void main(String[] args) { new Thread(() -> { Message msg = new Message(); msg.setInfo("第一个线程的消息"); Channel.setMessage(msg); Channel.send(); }, "消息发送者A").start(); new Thread(() -> { Message msg = new Message(); msg.setInfo("第二个线程的消息"); Channel.setMessage(msg); Channel.send(); }, "消息发送者B").start(); new Thread(() -> { Message msg = new Message(); msg.setInfo("第三个线程的消息"); Channel.setMessage(msg); Channel.send(); }, "消息发送者C").start(); } } // 执行结果 【消息发送者B消息发送】第三个线程的消息 【消息发送者A消息发送】第三个线程的消息 【消息发送者C消息发送】第三个线程的消息
出现了数据不同步的现象,在本程序中,在保持Channel核心结构不改变的情况下,需要考虑每个线程的独立操作问题。在这样的情况下,对于Channel类而言除了要保留要发送的消息之外,还要存放对每个线程的标记,这时候我们就可以使用ThreadLocal类来存放数据。
-
在ThreadLocal里面提供如下操作方法:
// 构造方法 public ThreadLocal(); // 设置数据 public void set(T value); // 取出数据 public T get(); // 删除数据 public void remove();
-
解决线程同步问题:
class Channel { private static final ThreadLocal<Message> THREAD_LOCAL = new ThreadLocal<Message>(); private Channel() {} public static void setMessage(Message m) { THREAD_LOCAL.set(m); } public static void send() { System.out.println("【" + Thread.currentThread().getName() + "消息发送】" + THREAD_LOCAL.get().getInfo()); } } class Message { private String info; public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } } public class ThreadLocalDemo { public static void main(String[] args) { new Thread(() -> { Message msg = new Message(); msg.setInfo("第一个线程的消息"); Channel.setMessage(msg); Channel.send(); }, "消息发送者A").start(); new Thread(() -> { Message msg = new Message(); msg.setInfo("第二个线程的消息"); Channel.setMessage(msg); Channel.send(); }, "消息发送者B").start(); new Thread(() -> { Message msg = new Message(); msg.setInfo("第三个线程的消息"); Channel.setMessage(msg); Channel.send(); }, "消息发送者C").start(); } } // 运行结果 【消息发送者B消息发送】第二个线程的消息 【消息发送者C消息发送】第三个线程的消息 【消息发送者A消息发送】第一个线程的消息
每一个线程通过ThreadLocal只允许保存一个数据,开发中它可以作为资源引用传递多线程安全问题解决方案