[英]How can I pass a just object instance to a thread in java, so that even if the instance value gets updated should not effect the thread using it
I am developing an application in which I continuously receive messages. 我正在开发一个我不断收到消息的应用程序。 I am storing these messages in an in-memory data structure (say List).
我将这些消息存储在内存数据结构中(比如List)。 I want to write those messages to a file but only after list size reaches some threshold value say 100 messages (perform batch processing on the messages).
我想将这些消息写入文件,但只有在列表大小达到某个阈值后才说100条消息(对消息执行批处理)。 One way is I can simply check the list size after every message is received and call a function to write messages to a file if Threshold value is reached.
一种方法是我可以在收到每条消息后简单地检查列表大小,如果达到阈值,则调用函数将消息写入文件。 But the problem with this approach is:
但这种方法的问题是:
Other way could be to spawn a new thread, which will write messages to a file independently. 其他方法可能是生成一个新线程,它将独立地将消息写入文件。 But when I pass the list (containing messages) to the thread for performing write operation, it gets updated with new messages which are continuously coming in. As a result newly arrived messages also gets written to the file which is not expected.
但是当我将列表(包含消息)传递给线程以执行写操作时,它会被新消息更新,这些消息会不断进入。因此,新到达的消息也会被写入到不期望的文件中。
This should not happen as I am intending the new messages to be written in the next batch. 这不应该发生,因为我打算在下一批中写入新消息。
Can someone suggest me a solution for this requirement, or any improvements in the above approach that can solve my issues. 有人可以建议我这个要求的解决方案,或上述方法的任何改进,可以解决我的问题。
I find a cleaner solution is to support auto-batching. 我发现更清洁的解决方案是支持自动批处理。 ie where the size of the batch adjusts with the rate of incoming data.
即批量大小随输入数据的速率调整。
To do this you can use a BlockingQueue 为此,您可以使用BlockingQueue
// unbound queue will not block the producer.
final BlockingQueue<T> queue = new LinkedBlockingQueue<T>();
// to add an element.
queue.add(element);
// to get a batch of data
List<T> list = new ArrayList<T>(maxElements);
while(writing) {
T t = queue.take(); // wait for at least one element.
list.add(t);
queue.drainTo(list, maxElements-1);
// process list, e.g. write to a file.
list.clear();
}
The benefit of this approach is that if the producer is very slow, you won't get elements held unreasonably long, but as the rate increases the batch size naturally grows to whatever will keep up with the producer which means you don't have to decide what is the best batch size to use. 这种方法的好处是,如果生产者非常慢,你不会让元素保持不合理的长,但随着速度的增加,批量大小自然会增长到跟上生产者的任何东西,这意味着你不需要决定使用的最佳批量大小。
I would suggest the following approach: 我建议采用以下方法:
AtomicReference
. AtomicReference
的消息列表的引用。 If you write to the list from a single thread, it will be enough to use a plain reference instead of the AtomicReference
. 如果从单个线程写入列表,则使用普通引用而不是
AtomicReference
就足够了。
It's important to understand that you never pass an object around in Java - only ever a reference (or a primitive value). 重要的是要理解你永远不会在Java中传递一个对象 - 只有一个引用 (或一个原始值)。
Options: 选项:
I'd recommend the latter approach, using the classes in the java.util.concurrent
package to implement it; 我建议使用后一种方法,使用
java.util.concurrent
包中的类来实现它; particularly BlockingQueue<E>
implementations. 特别是
BlockingQueue<E>
实现。
为什么主消息接收进程一旦将旧消息列表传递给文件写入线程就会创建新消息列表?
You can implement Custom BoundedQueue
using Condition which accepts say 100
objects and then write at one go. 您可以使用Condition实现Custom
BoundedQueue
,它接受100
对象,然后一次写入。
Now you can share this BoundedQueue
class instance with different threads which will put objects in it and there will be thread which will call writeAll()
method until you want to call it. 现在你可以用不同的线程共享这个
BoundedQueue
类实例,它将把对象放在其中,并且会有一个调用writeAll()
方法的线程,直到你想调用它为止。
BoundedBuffer boundedBuffer = new BoundedBuffer();
boundedBuffer.put("test"); .......
From writing thread do below 从写作线程做下面
boundedBuffer.writeAll();
Below is the sample code 下面是示例代码
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class BoundedBuffer {
final Lock lock = new ReentrantLock();
final Condition full = lock.newCondition();
final Condition empty = lock.newCondition();
final Object[] items = new Object[100];
int count;
public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length) {
empty.signal();
full.await();
}
items[count] = x;
++count;
} finally {
lock.unlock();
}
}
public void writeAll() throws InterruptedException {
lock.lock();
try {
while (count < items.length)
empty.await();
// Write to file here After write finished signal full condition
count = 0;
full.signal();
} finally {
lock.unlock();
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.