多线程开发中特别重要的类(解决了核心资源多线程并发资源访问的处理情况)
单线程分析范例:
public class ThreadLocalTest {
public static void main(String[] args) {
Message message =new Message();//实例化消息主体对象
message.setInfo("123123");//设置要发送的内容
Channel.setMessage(new Message());//设置要发送的消息
Channel.send();//发送消息
}
}
class Message {//要发送的消息体
private String info;
public void setInfo(String info) {
this.info = info;
}
public String getInfo() {
return info;
}
}
class Channel {//消息的发送通道
private static Message message;
public static void setMessage(Message m) {
message = m;
}
public static void send() {//发送消息
System.out.println("【消息发送】" + message.getInfo());// }
}
}
上面的程序时采用单线程的模式来处理的 。如果在多线程的状态下能否实现完全一致的效果呢?为此以下将启动三个线程进行处理。
范例:多线程的影响:
public class ThreadLocalTest {
public static void main(String[] args) {
new Thread(() -> {
Message message = new Message();//实例化消息主体对象
message.setInfo("第一个线程的消息");//设置要发送的内容
Channel.setMessage(message);//设置要发送的消息
Channel.send();//发送消息
}, "消息发送者A").start();
new Thread(() -> {
Message message = new Message();//实例化消息主体对象
message.setInfo("第二个线程的消息");//设置要发送的内容
Channel.setMessage(message);//设置要发送的消息
Channel.send();//发送消息
}, "消息发送者B").start();
new Thread(() -> {
Message message = new Message();//实例化消息主体对象
message.setInfo("第三个线程的消息");//设置要发送的内容
Channel.setMessage(message);//设置要发送的消息
Channel.send();//发送消息
}, "消息发送者C").start();
}
}
class Message {//要发送的消息体
private String info;
public void setInfo(String info) {
this.info = info;
}
public String getInfo() {
return info;
}
}
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());// }
}
}
多个线程同时发送消息的时候,消息之间产生了影响。同步的问题出现了。(一个线程的东西被另一个线程取出来了)
在保持Channel(所有发送的通道)核心结构不改变的情况下,需要考虑每个线程的独立操作问题。那么在这样的情况下就发现对于Channel类而言,除了要保留有发送的消息之外,还应该多存放有一个每一个线程的标记(当前线程)。解决方法:用ThreadLocal类来存放数据。在ThreadLocal类里面提供有如下方法:
- 构造方法:public ThreadLocal();
- 设置数据:public void set(T value);
- 取出数据:public T get();
- 删除数据:public void remove();
ThreadLocal存有两个对象:一个是线程对象currentThread
,一个是数据对象。
所有的数据都应被存放入ThreadLocal中。所有的数据操作都是通过ThreadLocal。
范例:解决线程同步问题
public class ThreadLocalTest {
public static void main(String[] args) {
new Thread(() -> {
Message message = new Message();//实例化消息主体对象
message.setInfo("第一个线程的消息");//设置要发送的内容
Channel.setMessage(message);//设置要发送的消息
Channel.send();//发送消息
}, "消息发送者A").start();
new Thread(() -> {
Message message = new Message();//实例化消息主体对象
message.setInfo("第二个线程的消息");//设置要发送的内容
Channel.setMessage(message);//设置要发送的消息
Channel.send();//发送消息
}, "消息发送者B").start();
new Thread(() -> {
Message message = new Message();//实例化消息主体对象
message.setInfo("第三个线程的消息");//设置要发送的内容
Channel.setMessage(message);//设置要发送的消息
Channel.send();//发送消息
}, "消息发送者C").start();
}
}
class Message {//要发送的消息体
private String info;
public void setInfo(String info) {
this.info = info;
}
public String getInfo() {
return info;
}
}
class Channel {//消息的发送通道
private static final ThreadLocal<Message> THREAD_LOCAL = new ThreadLocal<>();//很少会让你重新实例化,所以直接final
public static void setMessage(Message message) {
THREAD_LOCAL.set(message);
}
public Message getMessage() {
return THREAD_LOCAL.get();
}
public static void send() {//发送消息
System.out.println("【" + Thread.currentThread().getName() + "消息发送】" + THREAD_LOCAL.get().getInfo());// }
}
}
每一个线程通过ThreadLocal只允许保存一个数据。