I have a class with following method
public class Test {
private List l1;
public void send() {
for (<type> x : l1) {
//send to receivers and put a log in DB
}
}
}
This Test class is used by different threads which will fill the variable 'l1' with their own data and send them to receivers.
If I have to synchronize this to send data sequentially so that receivers get one full frame of data every time(without jumbling of data from different threads), should I synchronize on 'l1' or synchronize on the class Test.
I read the tutorials and samples but I still have this question.
You should synchronize on the object that represents you "shared state" (l1 in this case); you must ensure that every insert/read operation is synchronized
so you must have a synchronized(l1) {...} block for add (and remove) call and one while sending:
public void send() {
synchronized(l1) {
for (<type> x : l1) {
//send to receivers and put a log in DB
}
}
}
depending on you requirements you can also implement something more complex like:
public void send() {
synchronized(l1) {
List l2=new ArrayList(l1);
//clear l1?
}
for (<type> x : l2) {
//send to receivers and put a log in DB
}
}
and allow a grater degree of concurrency
Related
Imagine a datastream like this
A,A,B,A,C,C,C,A,B,A,A,A,B...
Now lets assume we have a StreamProcessor that will handle the stream. We can process A,B,C in parallel but individual As,Bs,Cs have to be processed in sequence.
Example:
Thread 1: Processes all As in sequence
Thread 2: Processes all Bs in sequence
and so on...
So for A,B,C I have a StreamProcessor (SP).
Each of the stream elements has a timestamp and thus can be ordered by time (It actually comes in the correct sequence). The elements have to be processed in time sequence.
So now I split up all my stream elements to their processors (SPA,SPB,SPC).
I have a TreeSet in ever SP where I add the elements.
So whenever there is a new element I basically do this:
public synchronized void onNewElementReceived(Element element) {
if (element== null) return;
treeSet.add(element);
if(treeSet.size()>30) logger.warn("There are many elements queueing up for processing");
threadPool.execute(() -> process(treeSet.first()));
}
private synchronized void process(Element element){
//Do the processing
}
This works fine if the stream is slow enough for process to terminate before there is the next element. But what if not? If there are more elements coming how can I make sure that the next element also is the next element that is going to be processed? In the end the operating system decides which Thread is fired when?
Edit: For clarity an example where this will fail:
Assume process() of A elements takes 1 second to execute. Now if the stream provides As faster then we can process them our treeSet will fill with elements of type A (I just realized it does not because we immediatly fetch it again, hmm another problem) anyway the main problem stays. If we receive elements every 100 ms for example we would request 10 executions of the process method, but the order would not be guaranteed anymore, because we do not know, which Runnable is going to be executed first by the system. We only ADDED them in the correct sequence but how to EXECUTE them in the correct sequence?
I could imagine just running a looper thread all the time fetching the first element of the queue and if there is none abort the process. Is that a good approach?
I would do it like this (PseudoCode-Like):
abstract class StreamProcessor extends Thread{
private ThreadSafeList<Element> elements;
void add(Element e) {
elements.addAtEnd(e);
}
#Override
public void run() {
while(hasNotFinished()) {
//If list has element, return the first element and remove it from the list, otherwise block until one is there and then return the first element and remove it.
Element e = elements.blockingRemoveFirst();
this.workWith(e);
}
}
abstract void workWith(Element e);
}
class StreamProcessorA extends StreamProcessor {
#Override
public void workWith(Element e) {
//Do something
}
}
class StreamProcessorB extends StreamProcessor {
#Override
public void workWith(Element e) {
//Do something
}
}
class StreamProcessorC extends StreamProcessor {
#Override
public void workWith(Element e) {
//Do something
}
}
class ElementReceiver {
private StreamProcessor A;
private StreamProcessor B;
private StreamProcessor C;
public synchronized void onNewElementReceived(Element e) {
if(e.type() /*Whatever*/ == ElementType.A) {
A.add(e);
}else if(e.type() == ElementType.B) {
B.add(e);
}else {
C.add(e);
}
}
}
This code consists of four threads.
The first thread receives the Element from some unspecified data source.
If this thread receives one, it checks what type it is (A,B or C).
Each of these types has a corresponding StreamProcessor. The onNewElementReceived will add the received element to the working set of the corresponding StreamProcessor.
Each of these StreamProcessor threads checks until they are for example killed and blocks until it has got an Element and then the method workWith is called that has to be implemented by each subclass.
I have a database which contains e-mails to be sent. I'm using multiple threads to send out these e-mails. The approach I'm using is that each thread will query the database, get N e-mails in memory and mark those as being sent. Another thread will see those N e-mails as marked and move on and fetch the next N entries.
Now this isn't working as before thread1 can update the entries as being sent, thread2 queries for the e-mails and thus both threads end up getting the same set of e-mails.
Each thread has its own connection to the database. Is that the root cause of this behaviour? Should I be just sharing one connection object across all the threads?
Or is there any better approach that I could use?
My recommendation is to have a single thread take care of querying the database, placing the retrieved emails in a thread-safe queue (e.g. an ArrayBlockingQueue, which has the advantage of being bounded); you can then have any number of threads removing and processing emails from this queue. The synchronization overhead on the ArrayBlockingQueue is fairly lightweight, and this way you don't need to use database transactions or anything like that.
class EmailChunk {
Email[] emails;
}
// only instantiate one of these
class DatabaseThread implements Runnable {
final BlockingQueue<EmailChunk> emailQueue;
public DatabaseThread(BlockingQueue<EmailChunk> emailQueue) {
this.emailQueue = emailQueue;
}
public void run() {
EmailChunk newChunk = // query database, create email chunk
// add newChunk to queue, wait 30 seconds if it's full
emailQueue.offer(newChunk, 30, TimeUnit.SECONDS);
}
}
// instantiate as many of these as makes sense
class EmailThread implements Runnable {
final BlockingQueue<EmailChunk> emailQueue;
public EmailThread(BlockingQueue<EmailChunk> emailQueue) {
this.emailQueue = emailQueue;
}
public void run() {
// take next chunk from queue, wait 30 seconds if queue is empty
emailChunk nextChunk = emailQueue.poll(30, TimeUnit.SECONDS);
}
}
class Main {
final int queueSize = 5;
public static void main(String[] args) {
BlockingQueue<EmailChunk> emailQueue = new ArrayBlockingQueue<>(queueSize);
// instantiate DatabaseThread and EmailThread objects with this queue
}
}
You need to have a way to share one method // code to control the concurrence. Sincronize the statements to get the emails and mark them. Then sent the e-mails. Something like this:
public void processMails(){
List<String> mails;
synchronized(this){
mails = getMails();
markMails(mails);
}
sendMails(mails);
}
This method could be in your DAO Facade where all threads can access.
EDIT:
if you have multiples instances of DAO class:
public void processMails(){
List<String> mails;
synchronize(DAO.class){
mails = getMails();
markMails(mails);
}
sendMails(mails);
}
Other alternative
private static final Object LOCK = new Object();
public void processMails(){
List<String> mails;
synchronize(LOCK){
mails = getMails();
markMails(mails);
}
sendMails(mails);
}
I've two threads. One for generating data, second for sending them to server. Is this a classic producer-consumer situation?
To do this I've constructed simple code for managing synchronised queue - I hope: I did it more or less correct? Could somebody answer me, please? My code is here below:
public ArrayList<String> Packets;
public synchronized void add_to_Queue (String data) {
Packets.add(data);
}
public synchronized void del_from_Queue (int position) {
Packets.remove(position);
}
public synchronized String read_from_ Queue(int position) {
return Packets.get(position);
}
public synchronized int number_of_element_of_Queue() {
return Packets.size();
}
First thread add new data by putting them using simple command:
add_to_Queue("XYZ);
Second one sending data in a loop:
while (OK)
{
try
{
while (number_of_element_of_Queue()>0)
{
out.write(read_from_Queue(0)+"\n");
out.flush;
del_from_Queue(0); // if no error delete just sent element
}
}
catch (IOException e1)
{
reconnect();
}
}
I think something is wrong because sending static data (simple static text instead of reading it from my "Queue") doesn't result in reconnection (i.e. after catch (IOException e1) ). But when I use presented code, it happens very often, especially after reconnection. It does it several times (send some data, reconnect, send some more data, again reconnect and so on).
Yeah, what happens if the queue is empty? You don't seem to be checking for that or handling it. But that is not the only condition you are not accounting for.
More generally, the implementation shown is not how a Queue works. Queues are first-in-first-out, no need for a position parameter. There is not a concept of "read" then "delete", those operations are usually atomic via a "take". You are best served by using an existing BlockingQueue implementation as opposed to writing your own.
The following is a simplified version of my current code. I am pretty sure I am not doing any thing wrong syntax-wise, and I can't locate my conceptual mistake.
This is sort of an observer pattern I tried to implement. I could not afford to inherit from Java.utils.observable as my class is already complicated and inherits from another class.
There are two parts here:
There's a Notifier class implementing Runnable :
public class Notifier implements Runnable{
public void run()
{
while(true)
{
MyDataType data = getData();
if(data.isChanged()==true)
{
refresh();
}
}
}
}
And then there is my main class which needs to respond to changes to MyDataType data.
public class abc {
private MyDataType data;
public void abc(){
Notifier notifier = new Notifier();
Thread thread = new Thread(notifier);
thread.start();
}
public MyDataType getData(){
return this.data;
}
public void refresh(){
MyDatatype data = getData();
//Do something with data
}
}
The problem : What's happening is that the notifier is calling refresh() when 'data' changes. However inside refresh(), when I do getData(), I am getting the old version of 'data'!
I should mention that there are other parts of the code which are calling the refresh() function too.
What am I overlooking?
Any other better solutions to this problem?
How should I approach designing Subject-Observer systems if I can't apply the default Java implementation out of the box?
when I do getData(), I am getting the old version of 'data'!
Your data field is shared among more than one thread so it must be marked with the volatile keyword.
private volatile MyDataType data;
This causes a "memory barrier" around the read and the the write that keeps the value visible to all threads. Even though the notifier thread is calling getData(), the value for data is being retrieved out if its memory cache. Without the memory barrier, the data value will be updated randomly or never.
As #JB mentioned in the comments, the volatile protects you against a re-assignment of the data field. If you update one of the fields within the current data value, the memory barrier will not be crossed that the notifier's memory will not be updated.
Looking back at your code, it looks like this is the case:
if(data.isChanged()==true)
{
refresh();
}
If data is not being assigned to a new object then making data to be volatile won't help you. You will have to:
Set some sort of volatile boolean dirty; field whenever data has been updated.
Update or read data within a synchronize block each and every time.
First, your data variable might be cached, so you will always need to get the latest value by making it volatile.
Second, what you are doing here is a producer / consumer pattern. This pattern is usually best implemented with messages. When you receive new data, you could create an immutable object and post it to the consumer thread (via a thread safe queue like a BlockingQueue) instead of having a shared variable.
Something along these lines:
public class Notifier extends Thread{
private BlockingQueue<E> consumerQueue = null;
public setConsumerQueue(BlockingQueue<E> val){
consumerQueue = val;
}
// main method where data is received from socket...
public void run(){
while(!interrupted()){
data = ... // got new data here
if(!data.isChanged()) continue;
// Post new data only when it has changed
if(consumerQueue!=null) consumerQueue.offer(data);
}
}
}
public class Consumer extends Thread{
private BlockingQueue<E> consumerQueue = new BlockingQueue<E>();
public Consumer (Producer val){
val.setConsumerQueue(consumerQueue);
}
public void run(){
while(!interrupted()){
data = consumerQueue.take();// block until there is data from producer
if(data !=null) processData(data);
}
}
}
I have a server that receives various xml messages from clients (one thread per client) and routes the messages to different functions depending on the message type. Eg. if the first element in the messages contains the string 'login' it signifies that this is a login message so route the message to the login() function.
Anyway, I want to make this message so things don't get messed up if multiple clients are connected and the dispatcher switches threads in middle of the message routing. So here is how I am routing the messages -
public void processMessagesFromClient(Client client)
{
Document message;
while (true)
{
try
{
message = client.inputStream.readObject();
/*
* Determine the message type
*/
String messageType = getMessageType(message);
// Route the message depending on its type
switch (messageType)
{
case LOGIN:
userModel.handleLogin();
...
...
...
etc...
}
} catch(Exception e) {}
}
So how can I make this thread safe? I figure I need to put a synchronise statement in somewhere but Im not sure where. Also Ive been reading around on the subject and I found this post which says there is an issue with using synchronise on 'this' -
https://stackoverflow.com/a/416198/1088617
And another post here which says singletons aren't suitable for using synchronise on (My class in the code above is a singleton) - https://stackoverflow.com/a/416202/1088617
Your class is already thread safe, because you are only using local variables.
Thread safety only comes into play when you access class state (ie fields), which your code doesn't (seem to) do.
What you are talking about is serialization - you want to funnel all message processing through one point to guarantee that message processing is one-at-a-time (starts and finishes atomically). The solution is simple: Employ a static synchronized method:
public void processMessagesFromClient(Client client) {
Document Message;
while (true) {
processMessage(client);
}
}
private static synchronized processMessage(Client client) {
try {
message = client.inputStream.readObject();
String messageType = getMessageType(message);
// Route the message depending on its type
switch (messageType) {
case LOGIN:
userModel.handleLogin();
...
etc...
}
} catch(Exception e) {}
}
FYI static synchronized methods use the Class object as the lock. This code will make your code behave like a single thread, which your question seems to want.
I would actually have a message handler thread which is responsible for reading incoming messages. This will then hand off processing to a worker thread to do the time consuming processing of the message. You can use the Java ThreadPoolExecutor to manage this.
If you already have 1 thread per connection, then the only thing that you have to synchronize are the functions which handle the events (i.e. functions like userModel.handleLogin()).
I guess the best solution should be to use a thread safe queue like the ConcurrentQueue and use a single working thread to pick up this values and run the actions one by one.
Provided you have one of these objects per thread, you don't have a problem. You only need to synchronized a shared object which can be modified by one of the threads.
public void processMessagesFromClient(Client client) {
while (true) {
processMessage(client);
}
}
private void processMessage(Client client) {
try {
Document message = client.inputStream.readObject();
String messageType = getMessageType(message);
// Route the message depending on its type
switch (messageType) {
case LOGIN:
userModel.handleLogin();
...
etc...
}
} catch(Exception e) {}
}
You need to know which resource should be only used be one thread at a certain time.
In your case it is likely that reading the next message needs to protected.
synchronize (lock) {
message = client.inputStream.readObject();
}
However, your code sample does not really show what needs to protected against concurrent access
The method itself is thread safe.
However, noting that this your class is a singleton, you might want to use double checked locking in your getInstance to ensure thread safety.
Also you should make sure your instance is set to static
class Foo {
private static volatile Foo instance = null;
public static Foo getInstance() {
if (instance == null)
{
synchronized(this)
{
if (instance == null)
instance = new Foo ();
}
}
return instance ;
}
}