Java 一个线程中的非空值,在另一个线程中为空
我正在用Java开发一个多客户端TCP服务器。由于服务器必须能够同时执行许多操作,因此我创建了一个线程,用于通过套接字向客户端发送数据。其定义如下:Java 一个线程中的非空值,在另一个线程中为空,java,multithreading,vert.x,blockingqueue,Java,Multithreading,Vert.x,Blockingqueue,我正在用Java开发一个多客户端TCP服务器。由于服务器必须能够同时执行许多操作,因此我创建了一个线程,用于通过套接字向客户端发送数据。其定义如下: public class MessageSender implements Runnable{ private OutputStream output; private volatile ArrayList<byte[]> messagesToSend; public MessageSender(Output
public class MessageSender implements Runnable{
private OutputStream output;
private volatile ArrayList<byte[]> messagesToSend;
public MessageSender(OutputStream _output)
{
output = _output;
messagesToSend = new ArrayList<byte[]>(0);
}
public void run()
{
while (true)
{
if (messagesToSend.size() > 0)
{
sendMessage(messagesToSend.get(0));
messagesToSend.remove(0);
}
}
}
public void setMessageToSend(Message message)
{
messagesToSend.add(message.getMessageHandler().getBytes());
}
public void sendMessage(byte[] bytes)
{
if (bytes == null)
{
System.out.println("bytes = null");
return ;
}
try
{
output.write(bytes, 0, bytes.length);
}
catch (IOException e)
{
System.out.println(e);
}
}
}
这是一个Vertx
处理程序,在从客户端接收特定消息时只调用一次。它被调用,通道_状态按预期实例化。在同一个线程中,我有一个Vertx计时器,在该计时器中,我向MessageSender
发送一个由channel\u status类包含的字节数组
vertx.setPeriodic(duration, id -> {
System.out.println(Arrays.toString(channel_test.getMessageHandler().getBytes()));
sender.setMessageToSend(channel_test);
});
如您所见,我正在打印它的值,以确保它不为null。而且,它在计时器中从不为空。但是当MessageSender收到它时,有时它是空的(有时我指的是大约1/50次)。为什么?这是一个并发问题吗
谢谢。将您的
运行方法更改为
public void run() {
while (true) {
synchronized(messagesToSend) {
while (messagesToSend.isEmpty()) {
messagesToSend.wait();
}
}
sendMessage(messagesToSend.get(0));
messagesToSend.remove(0);
}
}
和setMessageToSend()
as
public void setMessageToSend(Message message) {
messagesToSend.add(message.getMessageHandler().getBytes());
messagesToSend.notify();
}
将run
方法更改为
public void run() {
while (true) {
synchronized(messagesToSend) {
while (messagesToSend.isEmpty()) {
messagesToSend.wait();
}
}
sendMessage(messagesToSend.get(0));
messagesToSend.remove(0);
}
}
和setMessageToSend()
as
public void setMessageToSend(Message message) {
messagesToSend.add(message.getMessageHandler().getBytes());
messagesToSend.notify();
}
使ArrayList
volatile
保证在thread1中添加新元素时,thread2可以看到它
您应该使用支持的列表,例如:
messagesToSend = Collections.synchronizedList(new ArrayList<byte[]>(0));
A可以解决这个问题:
private BlockingQueue<byte[]> messagesToSend;
public MessageSender(OutputStream _output) {
output = _output;
messagesToSend = new LinkedBlockingQueue<>();
}
public void run() {
while (true) {
try {
sendMessage(messagesToSend.take()); // this will get blocked untill the queue is not empty
} catch (InterruptedException e) {
}
}
}
public void setMessageToSend(Message message) {
try {
messagesToSend.put(message.getMessageHandler().getBytes()); // put new element in the queue, check if run method is blocked, wake it up
} catch (InterruptedException e) {
}
}
private BlockingQueue messagesToSend;
public MessageSender(OutputStream\u输出){
输出=_输出;
messagesToSend=newlinkedblockingqueue();
}
公开募捐{
while(true){
试一试{
sendMessage(messagesToSend.take());//这将被阻止,直到队列不为空为止
}捕捉(中断异常e){
}
}
}
公共无效setMessageToSend(消息消息){
试一试{
messagesToSend.put(message.getMessageHandler().getBytes());//将新元素放入队列,检查run方法是否被阻止,将其唤醒
}捕捉(中断异常e){
}
}
制作ArrayList
volatile
确保在thread1中添加新元素时,thread2可以看到它
您应该使用支持的列表,例如:
messagesToSend = Collections.synchronizedList(new ArrayList<byte[]>(0));
A可以解决这个问题:
private BlockingQueue<byte[]> messagesToSend;
public MessageSender(OutputStream _output) {
output = _output;
messagesToSend = new LinkedBlockingQueue<>();
}
public void run() {
while (true) {
try {
sendMessage(messagesToSend.take()); // this will get blocked untill the queue is not empty
} catch (InterruptedException e) {
}
}
}
public void setMessageToSend(Message message) {
try {
messagesToSend.put(message.getMessageHandler().getBytes()); // put new element in the queue, check if run method is blocked, wake it up
} catch (InterruptedException e) {
}
}
private BlockingQueue messagesToSend;
public MessageSender(OutputStream\u输出){
输出=_输出;
messagesToSend=newlinkedblockingqueue();
}
公开募捐{
while(true){
试一试{
sendMessage(messagesToSend.take());//这将被阻止,直到队列不为空为止
}捕捉(中断异常e){
}
}
}
公共无效setMessageToSend(消息消息){
试一试{
messagesToSend.put(message.getMessageHandler().getBytes());//将新元素放入队列,检查run方法是否被阻止,将其唤醒
}捕捉(中断异常e){
}
}
不应该等待并在两个不同的线程中调用notify吗?setMessageToSend
是通过另一个线程调用的,因此notify将在另一个线程中调用,当另一个线程调用wait时,wait
和notify
工作在synchronized
方法或块不应该在两个不同的线程中调用wait和notify?setMessageToSend
是通过另一个线程调用的,因此notify将在另一个线程上调用,while wait由另一个调用wait
和notify
在synchronized
方法中工作,或者blockwait和notify在while中仍然需要较少的cpu周期loop@HemantPatel是,需要等待
和通知
。我认为阻塞队列
比呼叫等待
和通知
更干净。不过有一个问题。BlockingQueue是一个抽象类,不能实例化,对吗?也许我应该使用LinkedBlockingQueue?等待并通知仍需要较少的cpu周期loop@HemantPatel是,需要等待
和通知
。我认为阻塞队列
比呼叫等待
和通知
更干净。不过有一个问题。BlockingQueue是一个抽象类,不能实例化,对吗?也许我应该使用LinkedBlockingQueue?