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.
Related
I am trying to implement a simple synchronization strategy in android.
A service instantiates class A and calls it's method sendToServer() for every iteration of a loop. This results in multiple Async tasks being started and the service ends immediately. The service may run again anytime and repeat the process.
So, to prevent two Async tasks from taking the same input, i store the Ids in a synchronized list and check the list before i start the async task.
But i am confused which piece of code i need to put in a synchronized block? Do i define the entire method isAlreadyRunning() as synchronized? Or do i not need to define any synchronized block of code at all?
Here is my class :
public class A{
private static List<Integer> idList = Collections.synchronizedList(new ArrayList<Integer>());
private boolean isAlreadyRunning(id){
//iterate through the list and return true if the id is already present
....
}
private class sendToServerAsyncTask extends AsyncTask<Void, Void, Boolean>{
#Override
protected Boolean doInBackground(Void... params) {
//send http request
}
#Override
protected void onPostExecute(Boolean result){
idList.remove(id);
}
}
public void sendToServer(int id) {
if(isAlreadyRunning(id)){
// an async task is already running for this id.
//,so dont start the async task again, just exit
return;
else {
idList.add(id);
new sendToServerAsyncTask(id).execute();
}
}
}
As per Android's documentation
ASYNC TASK's ORDER OF EXECUTION
When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.
The instances of Asynctask are already placed in a queue maintained by the framework and they are executed sequentially i.e. only after one task finishes the other will start so there is no chance of issue due to parallel execution because it doesn't exist.
So you need not do anything and the framework will take care of it for you.
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.
I have a project I am working on where I need to improve my knowledge on Threads.
Scenario:
I have an Activity which calls a method Which use uses a thread:
Object soapResponse = soaphttp.fetchNextCatalogueRange(0, numberOfItems);
In the soaphttp class I have:
Thread soapThread = new Thread(new Runnable()
{
private Object serverResponse = new Object();
public void run()
{
// Do network stuff here
}
});
soapThread.start();
try
{
// crude synchronisation
soapThread.join();
}
The problem
Using join() blocks the UI thread.
If I dont use join() I get null pointer exceptions (data sync errors)
The Challenge:
In my activity I would like to do stuff on the UI thread while the soaphttp class is fetching data and then sync i.e tell the UI thread that the data is ready.
for example display a progress bar .. which will terminate when the data has finished being fetched.
How can I do this without having to use AsyncTask ?
At the very end of your thread's run() method, use one of the following:
the post() method of View class,
the runOnUiThread() method of Activity class
in order to refresh your UI in the UI thread.
You can use the same methods to somehow alter your UI at the start of the run() method (make same widgets disabled, show some kind of progress indicator...)
In my application , I have this logic when the user logins , it will call the below method , with all the symbols the user owns .
public void sendSymbol(String commaDelimitedSymbols) {
try {
// further logic
} catch (Throwable t) {
}
}
my question is that as this task of sending symbols can be completed slowly but must be completed , so is there anyway i can make this as a background task ??
Is this possible ??
please share your views .
Something like this is what you're looking for.
ExecutorService service = Executors.newFixedThreadPool(4);
service.submit(new Runnable() {
public void run() {
sendSymbol();
}
});
Create an executor service. This will keep a pool of threads for reuse. Much more efficient than creating a new Thread each time for each asynchronous method call.
If you need a higher degree of control over your ExecutorService, use ThreadPoolExecutor. As far as configuring this service, it will depend on your use case. How often are you calling this method? If very often, you probably want to keep one thread in the pool at all times at least. I wouldn't keep more than 4 or 8 at maximum.
As you are only calling sendSymbol once every half second, one thread should be plenty enough given sendSymbols is not an extremely time consuming routine. I would configure a fixed thread pool with 1 thread. You could even reuse this thread pool to submit other asynchronous tasks.
As long as you don't submit too many, it would be responsive when you call sendSymbol.
There is no really simple solution. Basically you need another thread which runs the method, but you also have to care about synchronization and thread-safety.
new Thread(new Runnable() {
public void run() {
sendSymbol(String commaDelimitedSymbols);
}
}).start();
Maybe a better way would be to use Executors
But you will need to case about thread-safety. This is not really a simple task.
It sure is possible. Threading is the way to go here. In Java, you can launch a new thread like this
Runnable backGroundRunnable = new Runnable() {
public void run(){
//Do something. Like call your function.
}};
Thread sampleThread = new Thread(backGroundRunnable);
sampleThread.start();
When you call start(), it launches a new thread. That thread will start running the run() function. When run() is complete, the thread terminates.
Be careful, if you are calling from a swing app, then you need to use SwingUtil instead. Google that up, sir.
Hope that works.
Sure, just use Java Threads, and join it to get the results (or other proper sync method, depends on your requirements)
You need to spawn a separate thread to perform this activity concurrently. Although this will not be a separate process, but you can keep performing other task while you complete sending symbols.
The following is an example of how to use threads. You simply subclass Runnable which contains your data and the code you want to run in the thread. Then you create a thread with that runnable object as the parameter. Calling start on the thread will run the Runnable object's run method.
public class MyRunnable implements Runnable {
private String commaDelimitedSymbols;
public MyRunnable(StringcommaDelimitedSymbols) {
this.commaDelimitedSymbols = commaDelimitedSymbols;
}
public void run() {
// Your code
}
}
public class Program {
public static void main(String args[]) {
MyRunnable myRunnable = new MyRunnable("...");
Thread t = new Thread(myRunnable)
t.start();
}
}
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.