Threads getting wrong member variable values - java

In my project I am facing weird issue with thread.
This issue is only occurring when I am running multiple thread at
once(load testing).
In my project there are multiple Interceptors which intercepts request/response at different level in application and send the request/response to WritetoFile class which writes the details into a flat file using log4j framework.
Below is the sample interceptor code. There are multiple interceptor and each can process in parallel.
/*we have multiple Interceptor class which will pre-process the
request/response and then send it to WritetoFile*/
public class IntercerptorA {
// some code ...
public synchronized void sendRequestToWritetoFile(IRequest request,IResponse response){
WritetoFile wtf = new WritetoFile(); //this class is responsible for writing request/response information into LOG file
wtf.setRequest(request);
wtf.setResponse(response);
Thread thread=new Thread(wtf, "t1");//**assume wtf.getRequest is having "ABC"**
thread.start();
}
}
Now suppose there 2 more Interceptor and has only single line difference in the code.
//For interceptorB
Thread thread=new Thread(wtf, "t2");//**assume wtf.getRequest is having "DEF"**
//For interceptorC
Thread thread=new Thread(wtf, "t3");//**assume wtf.getRequest is having "XYZ"**
Below is the code for WritetoFile class -:
public class WritetoFile implements Runnable{
private volatile IRequest request;
private volatile IResponse response;
public synchronized IRequest getRequest() {
return request;
}
public synchronized void setRequest(IRequest request) {
this.request = request;
}
public synchronized IResponse getResponse() {
return response;
}
public synchronized void setResponse(IResponse response) {
this.response = response;
}
#Override
public void run() {
// I have added synchronized as I was trying to resolve the issue
synchronized(WritetoFile.class){
putItInFile(this.request,this.response);
}
}
private synchronized void putItInFile (IRequest request,IResponse response){
// This is the logger where I find discrepancies
LOGGER.info("Current thread is : "+Thread.currentThread().getName()+" data is"+request);
//some code and method call
}
}
Having said that, now when I am running a single request the LOGGER.info("Current thread is : "+Thread.currentThread().getName()+" data is"+request); line is giving output as below -:
Current thread is t1 data is ABC
Current thread is t2 data is DEF
Current thread is t3 data is XYZ
which is perfectly fine. BUT on running multiple thread at once I am getting sometime wrong output as below -:
Current thread is t1 data is DEF
Current thread is t2 data is DEF
Current thread is t3 data is XYZ
It seems to be that before thread t1 can use the value of "wtf" object in method putItInFile , thread t2 have already reset the wtf value using setter in interceptorB. But what my thinking is, when I am creating new instance WritetoFile class for each thread ,how is thread t2 operation changing thread t1 cache. Please let me know where am I going wrong and what I need to change.
Thanks in advance :)

Using synchronized everywhere does not make a class thread safe.
In your case, as soon as WritetoFile.setRequest(request1) returns there is a window where the lock is not held and any other thread is free to call it before there is an opportunity for it to be used.
Rather than assigning the requests to an instance variable you would be better off adding them to one of the java.util.concurrent queue classes and consuming them from the queue in the Thread.run() method.
Have a look at the java.util.concurrent javadoc as there are heaps of examples in there.

Most likely the DEF request is getting intercepted at two different levels, resulting in the request getting logged twice.

Your problem is a textbook concurrency problem.
You have multiple threads running at the same time that are able to read/write variables.
In order to make sure that these values stay correct you need to add a lock around the code that modifies your variables so that only one thread can modify these variables at any one time.
1) code needs to wait until a method that modifies variables becomes available.
2) when a thread is done modifying a variable and is about to exit the code block it needs to notify the other waiting threads that it is done.
Please read the API and review your code, keeping the above points in mind you should have no problems fixing it.

Related

Is threre a way to comunicate between threads and exchange information like a getter method inside the runnable, in java

Is there a way to communicate between thread such as get variables with getters as they are being updated in a different thread
For example if im loading images in a runnable thread like so:
Thread t1 = new Thread(new Runnable(){
public void run(){
//Ido the loading here
}
}
is there a way i can communicate to that like get a value of a var for example:
Thread t1 = new Thread(new Runnable(){
public void run(){
//Ido the loading here
name = "dsad";
}
public void getName(){ return name }
}
but it dosnt seen to work
As for thread communicating, there's java.util.concurrent.Exchanger.
In your particular case, it also possible to use CompletableFuture from Java 8, since Exchanger allows multiple communications (both of threads continue executing), which is possibly not your case.
Manually creating threads may cause different issues:
creating thread each time is expensive operation,
creating lots of threads which run at the same time involves possible scheduler problems, memory issues (each thread has it's own stack, ...),
publishing values not in safe way (see Safe Publication and Safe Initialization topics) may cause data races, which are really bad
So, combination of java.util.concurrent.ExecutorService and java.util.concurrent.CompletableFuture may allow you thread-safe and easy readable way to perform asynchronous loading.
You need to create a new public type. Using an anonymous class means no other class can see its methods, as there's no type besides Runnable that they can see.
public class MyTask implements Runnable(){
private volatile String name;
public void run(){
//I do the loading here
name = "dsad";
}
public void getName(){ return name }
}

java thread communication, independent file reading and wiriting

Java. I have two threads. one will be continuously monitoring for some events and based on the events, it will be updating (addition or deletion) a file. the other thread which is a timer task event, will be updating the same file in regular intervals of time. I want the threads to update the file when the other thread is not accessing the file. I couldn't use locks as file updating code part is independent for each thread and in different java classes. how can i do so? thanks in advance.
You can use synchronization.
public synchronized void update() {
..
..
..
}
so only one thread access the method. Other will wait on the lock.
If you have add,update,delete method
then,
private static Object LOCK = new Object();
public void update() {
synchronized(LOCK) {
..
..
..
}
}
public void add() {
synchronized(LOCK) {
..
..
..
}
}
public void delete() {
synchronized(LOCK) {
..
..
..
}
}
So Only one thread can able to edit/delete/add the file.
if one thread is adding , second thread is trying to delete then it will wait first thread to add.
synchronized void updateFILE
{
//Your operation here
}
So at a time one thread can perform opetation.. You can have look at here
Perhaps you could:
Create a wrapper class around your unsafe file-updater-class.
Make that wrapper class thread-safe by adding your synchronization or locks that clearly defines the critical sections and handle all exceptions appropriately (for example, unlock the critical section in a finally-block)
Let the other threads call your wrapper class instead.

How to run thread after completing some specific worker thread

I created two swing worker thread class in my swing application. They are load thread, save thread
Load thread is used to load the data from rest service
Save thread is used to push the data to rest service.
My question is that,
How to execute my threads one by one when i create more instance for
load thread?
Save thread should be run after completing process of existing load
thread
Does any one guide me to get solution for this scenario?
Note: I am using Swing Worker class to call rest services.
You should start your save thread in the done method of your load thread.
You can pass your saveThread to the loadThread as constructor argument or define it as class member.
This should work for you;
SaveThread mySaveThread = new SaveThread();
LoadThread myLoadThread = new LoadThread();
class LoadThread extends SwingWorker<String, Object> {
#Override
public String doInBackground() {
//do your work
return "";
}
#Override
protected void done() {
try {
mySaveThread.execute();
} catch (Exception ignore) {
}
}
}
myLoadThread .execute();
If you want to load data from multiple threads, and save this data from one thread after ALL data will be loaded. You can try to use barriers. For example CountDownLatch can wait while all load threads finished their works.

What is the best way to pass information between threads?

I want to be listening to a server while my program is doing other things, when a message is received from the server I want to interpret it.
I know about threading but not sure completely on how it works. If I have a thread listening for the server how can I pass that data to the main thread for interpretation? What is the best way for the main thread to send data to the server? What is the use of the synchronized modifier?
If I have a thread listening for the server how can I pass that data to the main thread for interpretation? What is the best way for the main thread to send data to the server?
I'd use a BlockingQueue for this. You define a single BlockingQueue such as the LinkedBlockingQueue. Your listener class then calls queue.take() which will wait for your server to call queue.put(). It leaves all of the synchronization, waits, notifies, etc. to the Java class instead of your own code.
What is the use of the synchronized modifier?
I'd do some reading to understand more about this. This is not the sort of thing that can be answered in a short-ish SO response. The Java concurrency tutorial is a good place to start.
If you want synchronous communication between a main thread and a processing thread, you can use a SynchronousQueue.
The idea is that the main thread passes data to the processing thread by calling put(), and the processing thread calls take(). Both are blocking operations.
Note that if you want to send back a result, then things may get a bit more complex as the main thread has to know when the result is ready. A CountDownLatch is a good primitive for this. You can do something like this.
First let's define a datastructure to pass data around:
public class MethodCall {
public final String methodName;
public final Object[] args;
public final CountDownLatch resultReady;
public Object result;
public MethodCall(String methodName, Object[] args) {
this.methodName = methodName;
this.args = args;
this.resultReady = new CountDownLatch(1);
}
public void setResult(Object result) {
this.result = result;
resultReady.countDown();
}
public Object getResult() throws InterruptedException {
resultReady.await();
return result;
}
}
Define the queue to pass data around, visible by both threads:
public SynchronousQueue<MethodCall> methodCalls = new SynchronousQueue<MethodCall>();
To make a call from the main thread to the processing thread and wait for the result:
MethodCall call = new MethodCall(methodName, args);
methodCalls.put(call);
Object result = call.getResult();
In the processing thread, for instance in a run() method, you can then do:
for (;;) {
MethodCall call = methodCalls.take();
Object res = processStuff(call.methodName, call.args);
call.setResult(res);
}
Where processStuff implements your logic. Of course you should deal with exceptions as well, deal with exit cases, change MethodCall to have more specific things than methodName and args and an Object return, etc.
Go through some tutorials for understanding Java Threads.
http://www.journaldev.com/1079/java-thread-tutorial
Your problem seems to be like producer-consumer model, you can use BlockingQueue to achieve this task easily.
Java Blocking Queue

Why is my multi-threaded application being paused?

My multi-threaded application has a main class that creates multiple threads. The main class will wait after it has started some threads. The runnable class I created will get a file list, get a file, and remove a file by calling a web service. After the thread is done it will notify the main class to run again. My problem is it works for a while but possibly after an hour or so it will get to the bottom of the run method from the output I see in the log and that is it. The Java process is still running but it does not do anything based on what I am looking at in the log.
Main class methods:
Main method
while (true) {
// Removed the code here, it was just calling a web service to get a list of companies
// Removed code here was creating the threads and calling the start method for threads
mainClassInstance.waitMainClass();
}
public final synchronized void waitMainClass() throws Exception {
// synchronized (this) {
this.wait();
// }
}
public final synchronized void notifyMainClass() throws Exception {
// synchronized (this) {
this.notify();
// }
}
I originally did the synchronization on the instance but changed it to the method. Also no errors are being recorded in the web service log or client log. My assumption is I did the wait and notify wrong or I am missing some piece of information.
Runnable Thread Code:
At the end of the run method
// This is a class member variable in the runnable thread class
mainClassInstance.notifyMainClass();
The reason I did a wait and notify process because I do not want the main class to run unless there is a need to create another thread.
The purpose of the main class is to spawn threads. The class has an infinite loop to run forever creating and finishing threads.
Purpose of the infinite loop is for continually updating the company list.
I'd suggest moving from the tricky wait/notify to one of the higher-level concurrency facilities in the Java platform. The ExecutorService probably offers the functionality you require out of the box. (CountDownLatch could also be used, but it's more plumbing)
Let's try to sketch an example using your code as template:
ExecutorService execSvc = Executors.newFixedThreadPool(THREAD_COUNT);
while (true) {
// Removed the code here, it was just calling a web service to get a list of companies
List<FileProcessingTask> tasks = new ArrayList<FileProcessingTask>();
for (Company comp:companyList) {
tasks.add(new FileProcessingTask(comp));
}
List<Future<FileProcessingTask>> results = execSvc.invokeAll(tasks); // This call will block until all tasks are executed.
//foreach Future<FileProcessingTask> in results: check result
}
class FileProcessingTask implements Callable<FileResult> { // just like runnable but you can return a value -> very useful to gather results after the multi-threaded execution
FileResult call() {...}
}
------- edit after comments ------
If your getCompanies() call can give you all companies at once, and there's no requirement to check that list continuously while processing, you could simplify the process by creating all work items first and submit them to the executor service all at once.
List<FileProcessingTask> tasks = new ArrayList<FileProcessingTask>();
for (Company comp:companyList) {
tasks.add(new FileProcessingTask(comp));
}
The important thing to understand is that the executorService will use the provided collection as an internal queue of tasks to execute. It takes the first task, gives it to a thread of the pool, gathers the result, places the result in the result collection and then takes the next task in the queue.
If you don't have a producer/consumer scenario (cfr comments), where new work is produced at the same time that task are executed (consumed), then, this approach should be sufficient to parallelize the processing work among a number of threads in a simple way.
If you have additional requirements why the lookup of new work should happen interleaved from the processing of the work, you should make it clear in the question.

Categories

Resources