Java Thread which waits for new objects in collection - java

I have one thread which should execute some action when new object is added to collection. This collection is modified by several Callables. Thread which waits for new elements should be easy stopped after some time by boolean flag 'stopped'.
What are the possible ways for implementing that? I didn't find good examples of implementing that.

Well, you could wrap your collection in a custom one and register a listener. Example with LinkedBlockingQueue:
public class MyCollection<T> extends LinkedBlockingQueue<T> {
private final MyListener<T> listener;
public MyCollection(MyListener<T> listener) {
this.listener = listener;
}
#Override
public void put(T t) throws InterruptedException {
super.put(t);
listener.onPut(t);
}
}
public class MyListener<T> {
private final ExecutorService executorService = Executors.newSingleThreadExecutor();
public void onPut(T t) {
executorService.submit(() -> doSomething(t));
}
public void stop() {
executorService.shutdown();
// optional call to awaitTermination() here..
}
}

Related

The AsyncTask API is deprecated in Android 11. What are the alternatives?

Google is deprecating Android AsyncTask API in Android 11 and suggesting to use java.util.concurrent instead. you can check out the commit here
*
* #deprecated Use the standard <code>java.util.concurrent</code> or
* <a href="https://developer.android.com/topic/libraries/architecture/coroutines">
* Kotlin concurrency utilities</a> instead.
*/
#Deprecated
public abstract class AsyncTask<Params, Progress, Result> {
If you’re maintaining an older codebase with asynchronous tasks in Android, you’re likely going to have to change it in future. My question is that what should be proper replacement of the code snippet shown below using java.util.concurrent. It is a static inner class of an Activity. I am looking for something that will work with minSdkVersion 16
private static class LongRunningTask extends AsyncTask<String, Void, MyPojo> {
private static final String TAG = MyActivity.LongRunningTask.class.getSimpleName();
private WeakReference<MyActivity> activityReference;
LongRunningTask(MyActivity context) {
activityReference = new WeakReference<>(context);
}
#Override
protected MyPojo doInBackground(String... params) {
// Some long running task
}
#Override
protected void onPostExecute(MyPojo data) {
MyActivity activity = activityReference.get();
activity.progressBar.setVisibility(View.GONE);
populateData(activity, data) ;
}
}
You can directly use Executors from java.util.concurrent package.
I also searched about it and I found a solution in this Android Async API is Deprecated post.
Unfortunately, the post is using Kotlin, but after a little effort I have converted it into Java. So here is the solution.
ExecutorService executor = Executors.newSingleThreadExecutor();
Handler handler = new Handler(Looper.getMainLooper());
executor.execute(new Runnable() {
#Override
public void run() {
//Background work here
handler.post(new Runnable() {
#Override
public void run() {
//UI Thread work here
}
});
}
});
Pretty simple right? You can simplify it little more if you are using Java 8 in your project.
ExecutorService executor = Executors.newSingleThreadExecutor();
Handler handler = new Handler(Looper.getMainLooper());
executor.execute(() -> {
//Background work here
handler.post(() -> {
//UI Thread work here
});
});
Still, it cannot defeat kotlin terms of conciseness of the code, but better than the previous java version.
Hope this will help you. Thank You
private WeakReference<MyActivity> activityReference;
Good riddance that it's deprecated, because the WeakReference<Context> was always a hack, and not a proper solution.
Now people will have the opportunity to sanitize their code.
AsyncTask<String, Void, MyPojo>
Based on this code, Progress is actually not needed, and there is a String input + MyPojo output.
This is actually quite easy to accomplish without any use of AsyncTask.
public class TaskRunner {
private final Executor executor = Executors.newSingleThreadExecutor(); // change according to your requirements
private final Handler handler = new Handler(Looper.getMainLooper());
public interface Callback<R> {
void onComplete(R result);
}
public <R> void executeAsync(Callable<R> callable, Callback<R> callback) {
executor.execute(() -> {
final R result = callable.call();
handler.post(() -> {
callback.onComplete(result);
});
});
}
}
How to pass in the String? Like so:
class LongRunningTask implements Callable<MyPojo> {
private final String input;
public LongRunningTask(String input) {
this.input = input;
}
#Override
public MyPojo call() {
// Some long running task
return myPojo;
}
}
And
// in ViewModel
taskRunner.executeAsync(new LongRunningTask(input), (data) -> {
// MyActivity activity = activityReference.get();
// activity.progressBar.setVisibility(View.GONE);
// populateData(activity, data) ;
loadingLiveData.setValue(false);
dataLiveData.setValue(data);
});
// in Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
viewModel = ViewModelProviders.of(this).get(MyViewModel.class);
viewModel.loadingLiveData.observe(this, (loading) -> {
if(loading) {
progressBar.setVisibility(View.VISIBLE);
} else {
progressBar.setVisibility(View.GONE);
}
});
viewModel.dataLiveData.observe(this, (data) -> {
populateData(data);
});
}
This example used a single-threaded pool which is good for DB writes (or serialized network requests), but if you want something for DB reads or multiple requests, you can consider the following Executor configuration:
private static final Executor THREAD_POOL_EXECUTOR =
new ThreadPoolExecutor(5, 128, 1,
TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
One of the simplest alternative is to use Thread
new Thread(new Runnable() {
#Override
public void run() {
// do your stuff
runOnUiThread(new Runnable() {
public void run() {
// do onPostExecute stuff
}
});
}
}).start();
If your project supports JAVA 8, you can use lambda:
new Thread(() -> {
// do background stuff here
runOnUiThread(()->{
// OnPostExecute stuff here
});
}).start();
According to the Android documentation AsyncTask was deprecated in API level 30 and it is suggested to use the standard java.util.concurrent or Kotlin concurrency utilities instead.
Using the latter it can be achieved pretty simple:
Create generic extension function on CoroutineScope:
fun <R> CoroutineScope.executeAsyncTask(
onPreExecute: () -> Unit,
doInBackground: () -> R,
onPostExecute: (R) -> Unit
) = launch {
onPreExecute() // runs in Main Thread
val result = withContext(Dispatchers.IO) {
doInBackground() // runs in background thread without blocking the Main Thread
}
onPostExecute(result) // runs in Main Thread
}
Use the function with any CoroutineScope which has Dispatchers.Main context:
In ViewModel:
class MyViewModel : ViewModel() {
fun someFun() {
viewModelScope.executeAsyncTask(onPreExecute = {
// ... runs in Main Thread
}, doInBackground = {
// ... runs in Worker(Background) Thread
"Result" // send data to "onPostExecute"
}, onPostExecute = {
// runs in Main Thread
// ... here "it" is the data returned from "doInBackground"
})
}
}
In Activity or Fragment:
lifecycleScope.executeAsyncTask(onPreExecute = {
// ... runs in Main Thread
}, doInBackground = {
// ... runs in Worker(Background) Thread
"Result" // send data to "onPostExecute"
}, onPostExecute = {
// runs in Main Thread
// ... here "it" is the data returned from "doInBackground"
})
To use viewModelScope or lifecycleScope add next line(s) to dependencies of the app's build.gradle file:
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$LIFECYCLE_VERSION" // for viewModelScope
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$LIFECYCLE_VERSION" // for lifecycleScope
At the time of writing final LIFECYCLE_VERSION = "2.3.0-alpha05"
UPDATE:
Also we can implement progress updating using onProgressUpdate function:
fun <P, R> CoroutineScope.executeAsyncTask(
onPreExecute: () -> Unit,
doInBackground: suspend (suspend (P) -> Unit) -> R,
onPostExecute: (R) -> Unit,
onProgressUpdate: (P) -> Unit
) = launch {
onPreExecute()
val result = withContext(Dispatchers.IO) {
doInBackground {
withContext(Dispatchers.Main) { onProgressUpdate(it) }
}
}
onPostExecute(result)
}
Using any CoroutineScope (viewModelScope/lifecycleScope, see implementations above) with Dispatchers.Main context we can call it:
someScope.executeAsyncTask(
onPreExecute = {
// ... runs in Main Thread
}, doInBackground = { publishProgress: suspend (progress: Int) -> Unit ->
// ... runs in Background Thread
// simulate progress update
publishProgress(50) // call `publishProgress` to update progress, `onProgressUpdate` will be called
delay(1000)
publishProgress(100)
"Result" // send data to "onPostExecute"
}, onPostExecute = {
// runs in Main Thread
// ... here "it" is a data returned from "doInBackground"
}, onProgressUpdate = {
// runs in Main Thread
// ... here "it" contains progress
}
)
Use this class to execute background task in Background Thread this class is work for all android API version include Android 11 also this code is same work like AsyncTask with doInBackground and onPostExecute methods
public abstract class BackgroundTask {
private Activity activity;
public BackgroundTask(Activity activity) {
this.activity = activity;
}
private void startBackground() {
new Thread(new Runnable() {
public void run() {
doInBackground();
activity.runOnUiThread(new Runnable() {
public void run() {
onPostExecute();
}
});
}
}).start();
}
public void execute(){
startBackground();
}
public abstract void doInBackground();
public abstract void onPostExecute();
}
After copying the above class, you can then use it with this:
new BackgroundTask(MainActivity.this) {
#Override
public void doInBackground() {
//put you background code
//same like doingBackground
//Background Thread
}
#Override
public void onPostExecute() {
//hear is result part same
//same like post execute
//UI Thread(update your UI widget)
}
}.execute();
Android deprecated AsyncTask API in Android 11 to get rid of a share of problems to begin with.
So, what's now?
Threads
Executers
RxJava
Listenable Futures
Coroutines 🔥
Why Coroutines?
Coroutines are the Kotlin way to do asynchronous programming. Compiler
support is stable since Kotlin 1.3, together with a
kotlinx.coroutines library -
Structured Concurrency
Non-blocking, sequential code
Cancellation propagation
Natural Exception Handling
Here I created a Alternative for AsyncTask using Coroutines which can be used same as AsyncTask without changing much code base in your project.
Create a new Abstract class AsyncTaskCoroutine which takes input parameter and output parameter datatypes of-course these parameters are optional :)
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
abstract class AsyncTaskCoroutine<I, O> {
var result: O? = null
//private var result: O
open fun onPreExecute() {}
open fun onPostExecute(result: O?) {}
abstract fun doInBackground(vararg params: I): O
fun <T> execute(vararg input: I) {
GlobalScope.launch(Dispatchers.Main) {
onPreExecute()
callAsync(*input)
}
}
private suspend fun callAsync(vararg input: I) {
GlobalScope.async(Dispatchers.IO) {
result = doInBackground(*input)
}.await()
GlobalScope.launch(Dispatchers.Main) {
onPostExecute(result)
}
}
}
2 . Inside Activity use this as same as your old AsycnTask now
new AsyncTaskCoroutine() {
#Override
public Object doInBackground(Object[] params) {
return null;
}
#Override
public void onPostExecute(#Nullable Object result) {
}
#Override
public void onPreExecute() {
}
}.execute();
InCase if you need to send pass params
new AsyncTaskCoroutine<Integer, Boolean>() {
#Override
public Boolean doInBackground(Integer... params) {
return null;
}
#Override
public void onPostExecute(#Nullable Boolean result) {
}
#Override
public void onPreExecute() {
}
}.execute();
Google recommends using Java’s Concurrency framework or Kotlin Coroutines. but Rxjava end to have much more flexibility and features then java concurrency so gained quite a bit of popularity.
I actually wrote two Medium stories about it:
AsyncTas is deprecated now what
AsyncTas is deprecated now what part 2
The first one is with Java and a workaround with Runnable, the second is a Kotlin and coroutines solution.
Both are with code examples of course.
The accepted answer is good. But...
I didn't see cancel() method implementation
So my implementation with possibility to cancel the running task (simulating cancellation) is below.
Cancel is needed to not run postExecute() method in case of task interruption.
public abstract class AsyncTaskExecutor<Params> {
public static final String TAG = "AsyncTaskRunner";
private static final Executor THREAD_POOL_EXECUTOR =
new ThreadPoolExecutor(5, 128, 1,
TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
private final Handler mHandler = new Handler(Looper.getMainLooper());
private boolean mIsInterrupted = false;
protected void onPreExecute(){}
protected abstract Void doInBackground(Params... params);
protected void onPostExecute(){}
protected void onCancelled() {}
#SafeVarargs
public final void executeAsync(Params... params) {
THREAD_POOL_EXECUTOR.execute(() -> {
try {
checkInterrupted();
mHandler.post(this::onPreExecute);
checkInterrupted();
doInBackground(params);
checkInterrupted();
mHandler.post(this::onPostExecute);
} catch (InterruptedException ex) {
mHandler.post(this::onCancelled);
} catch (Exception ex) {
Log.e(TAG, "executeAsync: " + ex.getMessage() + "\n" + Debug.getStackTrace(ex));
}
});
}
private void checkInterrupted() throws InterruptedException {
if (isInterrupted()){
throw new InterruptedException();
}
}
public void cancel(boolean mayInterruptIfRunning){
setInterrupted(mayInterruptIfRunning);
}
public boolean isInterrupted() {
return mIsInterrupted;
}
public void setInterrupted(boolean interrupted) {
mIsInterrupted = interrupted;
}
}
Example of using this class:
public class MySearchTask extends AsyncTaskExecutor<String> {
public MySearchTask(){
}
#Override
protected Void doInBackground(String... params) {
// Your long running task
return null;
}
#Override
protected void onPostExecute() {
// update UI on task completed
}
#Override
protected void onCancelled() {
// update UI on task cancelled
}
}
MySearchTask searchTask = new MySearchTask();
searchTask.executeAsync("Test");
Here I also created an Alternative for AsyncTask using abstract class and it can be just copied as a class.
/app/src/main/java/../AsyncTasks.java
public abstract class AsyncTasks {
private final ExecutorService executors;
public AsyncTasks() {
this.executors = Executors.newSingleThreadExecutor();
}
private void startBackground() {
onPreExecute();
executors.execute(new Runnable() {
#Override
public void run() {
doInBackground();
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
onPostExecute();
}
});
}
});
}
public void execute() {
startBackground();
}
public void shutdown() {
executors.shutdown();
}
public boolean isShutdown() {
return executors.isShutdown();
}
public abstract void onPreExecute();
public abstract void doInBackground();
public abstract void onPostExecute();
}
Implementation/ use of the above class
new AsyncTasks() {
#Override
public void onPreExecute() {
// before execution
}
#Override
public void doInBackground() {
// background task here
}
#Override
public void onPostExecute() {
// Ui task here
}
}.execute();
My custom replacement: https://github.com/JohnyDaDeveloper/AndroidAsync
It only works when the app is running (more specifically the activity which scheduled the task), but it's capable of updating the UI after the background task was completed
EDIT: My AsyncTask no longer reqires Activiy to function.
Just replace the whole class with this Thread and put it in a method to pass variables
new Thread(() -> {
// do background stuff here
runOnUiThread(()->{
// OnPostExecute stuff here
});
}).start();
and in Fragment add the Context to the runOnUiThread() methode:
new Thread(() -> {
// do background stuff here
context.runOnUiThread(()->{
// OnPostExecute stuff here
});
}).start();
You can use this custom class as an alternative of the AsyncTask<>, this is the same as AsyncTask so you not need to apply extra efforts for the same.
import android.os.Handler;
import android.os.Looper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class TaskRunner {
private static final int CORE_THREADS = 3;
private static final long KEEP_ALIVE_SECONDS = 60L;
private static TaskRunner taskRunner = null;
private Handler handler = new Handler(Looper.getMainLooper());
private ThreadPoolExecutor executor;
private TaskRunner() {
executor = newThreadPoolExecutor();
}
public static TaskRunner getInstance() {
if (taskRunner == null) {
taskRunner = new TaskRunner();
}
return taskRunner;
}
public void shutdownService() {
if (executor != null) {
executor.shutdown();
}
}
public void execute(Runnable command) {
executor.execute(command);
}
public ExecutorService getExecutor() {
return executor;
}
public <R> void executeCallable(#NonNull Callable<R> callable, #NonNull OnCompletedCallback<R> callback) {
executor.execute(() -> {
R result = null;
try {
result = callable.call();
} catch (Exception e) {
e.printStackTrace(); // log this exception
} finally {
final R finalResult = result;
handler.post(() -> callback.onComplete(finalResult));
}
});
}
private ThreadPoolExecutor newThreadPoolExecutor() {
return new ThreadPoolExecutor(
CORE_THREADS,
Integer.MAX_VALUE,
KEEP_ALIVE_SECONDS,
TimeUnit.SECONDS,
new SynchronousQueue<>()
);
}
public interface OnCompletedCallback<R> {
void onComplete(#Nullable R result);
}
}
How to use it? Please follow the below examples.
With lambda expressions
TaskRunner.getInstance().executeCallable(() -> 1, result -> {
});
TaskRunner.getInstance().execute(() -> {
});
Without lambda expressions
TaskRunner.getInstance().executeCallable(new Callable<Integer>() {
#Override
public Integer call() throws Exception {
return 1;
}
}, new TaskRunner.OnCompletedCallback<Integer>() {
#Override
public void onComplete(#Nullable Integer result) {
}
});
TaskRunner.getInstance().execute(new Runnable() {
#Override
public void run() {
}
});
Note: Don't forget to shutdown executors service
TaskRunner.getInstance().shutdownService();
You can migrate to next approaches depends your needs
Thread + Handler
Executor
Future
IntentService
JobScheduler
RxJava
Coroutines (Kotlin)
[Android async variants]
My answer is similar to the others, but it is easier to read imo.
This is the class:
public class Async {
private static final ExecutorService executorService = Executors.newCachedThreadPool();
private static final Handler handler = new Handler(Looper.getMainLooper());
public static <T> void execute(Task<T> task) {
executorService.execute(() -> {
T t = task.doAsync();
handler.post(() -> {
task.doSync(t);
});
});
}
public interface Task<T> {
T doAsync();
void doSync(T t);
}
}
And here's an example on how to use it:
String url;
TextView responseCodeText;
Async.execute(new Async.Task<Integer>() {
#Override
public Integer doAsync() {
try {
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
return connection.getResponseCode();
} catch (IOException e) {
return null;
}
}
#Override
public void doSync(Integer responseCode) {
responseCodeText.setText("responseCode=" + responseCode);
}
});
This is my code
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public abstract class AsyncTaskRunner<T> {
private ExecutorService executorService = null;
private Set<Callable<T>> tasks = new HashSet<>();
public AsyncTaskRunner() {
this.executorService = Executors.newSingleThreadExecutor();
}
public AsyncTaskRunner(int threadNum) {
this.executorService = Executors.newFixedThreadPool(threadNum);
}
public void addTask(Callable<T> task) {
tasks.add(task);
}
public void execute() {
try {
List<Future<T>> features = executorService.invokeAll(tasks);
List<T> results = new ArrayList<>();
for (Future<T> feature : features) {
results.add(feature.get());
}
this.onPostExecute(results);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
this.onCancelled();
} finally {
executorService.shutdown();
}
}
protected abstract void onPostExecute(List<T> results);
protected void onCancelled() {
// stub
}
}
And usage example.
Extends the AsyncTaskRunner class,
class AsyncCalc extends AsyncTaskRunner<Integer> {
public void addRequest(final Integer int1, final Integer int2) {
this.addTask(new Callable<Integer>() {
#Override
public Integer call() throws Exception {
// Do something in background
return int1 + int2;
}
});
}
#Override
protected void onPostExecute(List<Integer> results) {
for (Integer answer: results) {
Log.d("AsyncCalc", answer.toString());
}
}
}
then use it!
AsyncCalc calc = new AsyncCalc();
calc.addRequest(1, 2);
calc.addRequest(2, 3);
calc.addRequest(3, 4);
calc.execute();
AsyncTask class does not seem to be removed any time soon, but we did simply un-deprecate it anyway, because:
We didn't want to add lots of suppress annotations.
The alternative solutions have too much boiler-plate, or in most cases, without any real advantage vs AsyncTask.
We did not want to re-invent the wheel.
We didn't want to fear the day it will finally be removed.
Refactoring takes too much time.
Example
Simply add below file to your project, then search for "android.os.AsyncTask" imports, and replase all to the packge you did choose for said file.
As you may already know, this is no big deal, and is basically what the well known AndroidX library does all the time.
Get AsyncTask.java file at: https://gist.github.com/top-master/0efddec3e2c35d77e30331e8c3bc725c
Docs says:
AsyncTask This class was deprecated in API level 30. Use the standard
java.util.concurrent or Kotlin concurrency utilities instead.
You need to use Handler or coroutines instead AsyncTask.
Use Handler for Java
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
// Your Code
}
}, 3000);
Use Handler for Kotlin
Handler(Looper.getMainLooper()).postDelayed({
// Your Code
}, 3000)

How can i know threads jobs are done?

In class B how can i know jobs of threads are finished? In after properties some worker are running. In class B, I need to know if worker are done?
public class A implements InitializingBean{
public void method1(){
...
}
#Override
public void afterPropertiesSet() throws Exception {
System.out.print("test after properties set");
// send threads to executorService
ExecutorService executorService = Executors
.newFixedThreadPool(4);
for (int i = 0; i < 4; i++) {
Worker worker = new Worker();
executorService.submit(worker);
}
}
}
public class Worker implements Callable<Void>{
#Override
public void call(){
...
}
}
public class B{
public void methodB(){
A a = new A();
a.method1();
///Here How can i know the job of the workers are finished?
}
}
Use a listener/callback pattern to have the thread report completion to a listener. This simple example should show the process:
public interface ThreadCompleteListener {
void workComplete();
}
public class NotifyingThread extends Thread {
private Set<ThreadCompleteListener> listeners;
// setter method(s) for adding/removing listeners to go here
#Override
public void run() {
// do stuff
notifyListeners();
}
private void notifyListeners() {
for (ThreadCompleteListener listener : listeners) {
listener.workComplete(); // notify the listening class
}
}
}
in your listening class:
NotifyingThread t = new NotifyingThread();
t.addListener(new ThreadCompleteListener() {
void workComplete() {
// do something
}
});
t.start();
You could use a Future implementation for your thread. It provides a Future#isDone()
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#isDone()
In general, it is usually more useful to be notified via a callback when jobs complete. However, since others have posted answers which follow that model, I'll instead post a solution that simply allows you to poll and ask whether the jobs are finished, in case this is what fits the needs of your application better.
public static interface InitializingBean{
public void afterPropertiesSet() throws Exception;
}
public static class A implements InitializingBean{
private List<Future<Void>> submittedJobs = Collections.synchronizedList(new ArrayList<Future<Void>>());
public void method1(){
//do stuff
}
#Override
public void afterPropertiesSet() throws Exception {
System.out.print("test after properties set");
// send threads to executorService
ExecutorService executorService = Executors
.newFixedThreadPool(4);
synchronized (submittedJobs) {
for (int i = 0; i < 4; i++) {
Worker worker = new Worker();
submittedJobs.add(executorService.submit(worker));
}
}
}
/**
* Allows you to poll whether all jobs are finished or not.
* #return
*/
public boolean areAllJobsFinished(){
synchronized (submittedJobs) {
for(Future<Void> task : submittedJobs){
if(!task.isDone()){
return false;
}
}
return true;
}
}
}
public static class Worker implements Callable<Void>{
#Override
public Void call(){
//do worker job
return null; //to satisfy compiler that we're returning something.
}
}
public static class B{
public void methodB(){
A a = new A();
a.method1();
if(a.areAllJobsFinished()){
System.out.println("Congrats, everything is done!");
} else {
System.out.println("There's still some work being done :-(");
}
}
}
If you'd like to wait in that thread that starts the ExecutorService, you can actually use the awaitTermination method.
At the end of you afterPropertiesSet method, you should add:
executorService.shutdown();
After this you then add:
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS)
This causes the thread to wait for all the executorService's tasks to be done and then continues. So place any code you want to execute after the call to awaitTermination.

Right Approach for a General Purpose Batching Class

I'm looking for a class that will allow me to add items to process and when the item count equals the batch size performs some operation. I would use it something like this:
Batcher<Token> batcher = new Batcher<Token>(500, Executors.newFixedThreadPool(4)) {
public void onFlush(List<Token> tokens) {
rest.notifyBatch(tokens);
}
};
tokens.forEach((t)->batcher.add(t));
batcher.awaitDone();
After #awaitDone I know that all tokens have been notified. The #onFlush might do anything, for example, I might want to batch inserts into a database. I would like #onFlush invocations to be put into a Executor.
I came up with a solution for this but it seems like a lot of code, so my question is this, is there a better way I should be doing this? Is there an existing class other than the one I implemented or a better way to implement this? Seems like my solution has a lot of moving pieces.
Here's the code I came up with:
/**
* Simple class to allow the batched processing of items and then to alternatively wait
* for all batches to be completed.
*/
public abstract class Batcher<T> {
private final int batchSize;
private final ArrayBlockingQueue<T> batch;
private final Executor executor;
private final Phaser phaser = new Phaser(1);
private final AtomicInteger processed = new AtomicInteger(0);
public Batcher(int batchSize, Executor executor) {
this.batchSize = batchSize;
this.executor = executor;
this.batch = new ArrayBlockingQueue<>(batchSize);
}
public void add(T item) {
processed.incrementAndGet();
while (!batch.offer(item)) {
flush();
}
}
public void addAll(Iterable<T> items) {
for (T item : items) {
add(item);
}
}
public int getProcessedCount() {
return processed.get();
}
public void flush() {
if (batch.isEmpty())
return;
final List<T> batched = new ArrayList<>(batchSize);
batch.drainTo(batched, batchSize);
if (!batched.isEmpty())
executor.execute(new PhasedRunnable(batched));
}
public abstract void onFlush(List<T> batch);
public void awaitDone() {
flush();
phaser.arriveAndAwaitAdvance();
}
public void awaitDone(long duration, TimeUnit unit) throws TimeoutException {
flush();
try {
phaser.awaitAdvanceInterruptibly(phaser.arrive(), duration, unit);
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
private class PhasedRunnable implements Runnable {
private final List<T> batch;
private PhasedRunnable(List<T> batch) {
this.batch = batch;
phaser.register();
}
#Override
public void run() {
try {
onFlush(batch);
}
finally {
phaser.arrive();
}
}
}
}
A Java 8 solution would be great. Thanks.
What’s striking me is that your code doesn’t work with more than one thread adding items to a single Batcher instance. If we turn this limitation into the specified use case, there is no need to use specialized concurrent classes internally. So we can accumulate into an ordinary ArrayList and swap this list with a new one when the capacity is exhausted, without the need to copy items. This allows simplifying the code to
public class Batcher<T> implements Consumer<T> {
private final int batchSize;
private final Executor executor;
private final Consumer<List<T>> actualAction;
private final Phaser phaser = new Phaser(1);
private ArrayList<T> batch;
private int processed;
public Batcher(int batchSize, Executor executor, Consumer<List<T>> c) {
this.batchSize = batchSize;
this.executor = executor;
this.actualAction = c;
this.batch = new ArrayList<>(batchSize);
}
public void accept(T item) {
processed++;
if(batch.size()==batchSize) flush();
batch.add(item);
}
public int getProcessedCount() {
return processed;
}
public void flush() {
List<T> current = batch;
if (batch.isEmpty())
return;
batch = new ArrayList<>(batchSize);
phaser.register();
executor.execute(() -> {
try {
actualAction.accept(current);
}
finally {
phaser.arrive();
}
});
}
public void awaitDone() {
flush();
phaser.arriveAndAwaitAdvance();
}
public void awaitDone(long duration, TimeUnit unit) throws TimeoutException {
flush();
try {
phaser.awaitAdvanceInterruptibly(phaser.arrive(), duration, unit);
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
regarding Java 8 specific improvements, it uses a Consumer which allows to specify the final action via lambda expression without the need to subclass Batcher. Further, the PhasedRunnable is replaced by a lambda expression. As another simplification, Batcher<T> implements Consumer<T> which elides the need for a method addAll as every Iterable supports forEach(Consumer<? super T>).
So the use case now looks like:
Batcher<Token> batcher = new Batcher<>(
500, Executors.newFixedThreadPool(4), currTokens -> rest.notifyBatch(currTokens));
tokens.forEach(batcher);
batcher.awaitDone();

Executor wait for ever in a singleton class

I have implemented a singleton (manager) to manage some related tasks, inside this manager I am using an executor to handle 10 task at the same time, I was using linkedBlockingQueue with no limit, and that's working good so far, but now I need to set a limitation to my executor queue because I have a lot of tasks (hundreds of thousands tasks), and I don’t want to put them all in my queue that causing me a performance issues, so what I have done:
here is my Executor :
public class MyThreadPoolExecutor extends ThreadPoolExecutor {
public MyThreadPoolExecutor(int corePoolSize, BlockingQueue<Runnable> workQueue) {
super(corePoolSize, corePoolSize + 5, 500, TimeUnit.MILLISECONDS, workQueue);
}
#Override
protected void beforeExecute(Thread t, Runnable r) {
super.beforeExecute(t, r);
//Do something to my task
}
#Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if(t != null) {
//
} else {
//Do something to my task
}
}
}
and here is my manager :
public final class MyManager {
private static MyManager manager = new MyManager();
public static final int queueMaxSize = 100;
private BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<Runnable>(queueMaxSize);
private ExecutorService executor = new MyThreadPoolExecutor(10, workQueue);
/**
* constructor
*/
private MyManager() {}
public static MyManager getInstance(){
if (manager == null){
synchronized(MyManager.class){
if (manager == null){
manager = new MyManager();
}
}
}
return manager;
}
/**
*/
public void executeTask(Integer key){
executeTask(key, Locale.getDefault());
}
/**
*/
public void executeTask(Integer key, Locale locale) {
Tasker task = new Tasker(key, locale);
executor.execute(task);
}
}
and here the class that asking to do the tasks :
public class MyClass {
public void doTasks() {
//geting my tasks in array of list, its holding more than 900 000 tasks,
//sometimes its holding up to 10 million task like :
MyManager.getInstance().isFull() {\\wait, then ask again}
ArrayList<Integer> myTasks = getAllTasksIds();
for(Integer id : myTasks) {
//if i perform a waiting here it will be waiting for ever.
MyManaget.getInstance().executeTask(id);
}
}
}
What I want exactly to wait the executor until finish his queue tasks, then re-full it again.
But the problem is when I try to wait based on queue size, the executor won’t work, and its wait forever because the queue still full.
Why wouldn't you just use a bounded blocking queue (i.e. specify a bound of a BlockingQueue)? If you use a bounded blocking queue (of which size you can choose yourself), your producer will block when the queue is full, and will resume publishing tasks when a task is consumed from a queue. This way, you can avoid putting too much stuff too quickly onto the queue, but also avoid putting too less on the queue. That's kind of the point of blocking queues...
I tested your code but instead of using ArrayBlockingQueue I extended it with this... And it works. Try it:
public static class MyBlockingQueue extends ArrayBlockingQueue<Runnable> {
private static final long serialVersionUID= -9016421283603545618L;
public static Lock lock= new ReentrantLock();
public static Condition condition= lock.newCondition();
public static volatile Boolean isWaiting= false;
public MyBlockingQueue(int capacity) {
super(capacity, true);
}
#Override
public boolean offer(Runnable e) {
if (remainingCapacity() == 0) {
try {
isWaiting= true;
condition.await();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
return super.offer(e);
}
#Override
public Runnable take() throws InterruptedException {
Runnable take= super.take();
if (remainingCapacity() > 0 && isWaiting) {
isWaiting= false;
condition.signal();
}
return take;
}
}

Controlling Task execution order with ExecutorService

I have a process which delegates asynch tasks to a pool of threads. I need to ensure that certain tasks are executed in order.
So for example
Tasks arrive in order
Tasks a1, b1, c1, d1 , e1, a2, a3, b2, f1
Tasks can be executed in any order except where there is a natural dependancy, so a1,a2,a3 must be processed in that order by either allocating to the same thread or blocking these until I know the previous a# task was completed.
Currently it doesn't use the Java Concurrency package, but I'm considering changing to take avantage of the thread management.
Does anyone have a similar solution or suggestions of how to achieve this
I write own Executor that warrants task ordering for tasks with same key. It uses map of queues for order tasks with same key. Each keyed task execute next task with the same key.
This solution don't handle RejectedExecutionException or other exceptions from delegated Executor! So delegated Executor should be "unlimited".
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.Executor;
/**
* This Executor warrants task ordering for tasks with same key (key have to implement hashCode and equal methods correctly).
*/
public class OrderingExecutor implements Executor{
private final Executor delegate;
private final Map<Object, Queue<Runnable>> keyedTasks = new HashMap<Object, Queue<Runnable>>();
public OrderingExecutor(Executor delegate){
this.delegate = delegate;
}
#Override
public void execute(Runnable task) {
// task without key can be executed immediately
delegate.execute(task);
}
public void execute(Runnable task, Object key) {
if (key == null){ // if key is null, execute without ordering
execute(task);
return;
}
boolean first;
Runnable wrappedTask;
synchronized (keyedTasks){
Queue<Runnable> dependencyQueue = keyedTasks.get(key);
first = (dependencyQueue == null);
if (dependencyQueue == null){
dependencyQueue = new LinkedList<Runnable>();
keyedTasks.put(key, dependencyQueue);
}
wrappedTask = wrap(task, dependencyQueue, key);
if (!first)
dependencyQueue.add(wrappedTask);
}
// execute method can block, call it outside synchronize block
if (first)
delegate.execute(wrappedTask);
}
private Runnable wrap(Runnable task, Queue<Runnable> dependencyQueue, Object key) {
return new OrderedTask(task, dependencyQueue, key);
}
class OrderedTask implements Runnable{
private final Queue<Runnable> dependencyQueue;
private final Runnable task;
private final Object key;
public OrderedTask(Runnable task, Queue<Runnable> dependencyQueue, Object key) {
this.task = task;
this.dependencyQueue = dependencyQueue;
this.key = key;
}
#Override
public void run() {
try{
task.run();
} finally {
Runnable nextTask = null;
synchronized (keyedTasks){
if (dependencyQueue.isEmpty()){
keyedTasks.remove(key);
}else{
nextTask = dependencyQueue.poll();
}
}
if (nextTask!=null)
delegate.execute(nextTask);
}
}
}
}
When I've done this in the past I've usually had the ordering handled by a component which then submits callables/runnables to an Executor.
Something like.
Got a list of tasks to run, some with dependencies
Create an Executor and wrap with an ExecutorCompletionService
Search all tasks, any with no dependencies, schedule them via the completion service
Poll the completion service
As each task completes
Add it to a "completed" list
Reevaluate any waiting tasks wrt to the "completed list" to see if they are "dependency complete". If so schedule them
Rinse repeat until all tasks are submitted/completed
The completion service is a nice way of being able to get the tasks as they complete rather than trying to poll a bunch of Futures. However you will probably want to keep a Map<Future, TaskIdentifier> which is populated when a task is schedule via the completion service so that when the completion service gives you a completed Future you can figure out which TaskIdentifier it is.
If you ever find yourself in a state where tasks are still waiting to run, but nothing is running and nothing can be scheduled then your have a circular dependency problem.
When you submit a Runnable or Callable to an ExecutorService you receive a Future in return. Have the threads that depend on a1 be passed a1's Future and call Future.get(). This will block until the thread completes.
So:
ExecutorService exec = Executor.newFixedThreadPool(5);
Runnable a1 = ...
final Future f1 = exec.submit(a1);
Runnable a2 = new Runnable() {
#Override
public void run() {
f1.get();
... // do stuff
}
}
exec.submit(a2);
and so on.
You can use Executors.newSingleThreadExecutor(), but it will use only one thread to execute your tasks. Another option is to use CountDownLatch. Here is a simple example:
public class Main2 {
public static void main(String[] args) throws InterruptedException {
final CountDownLatch cdl1 = new CountDownLatch(1);
final CountDownLatch cdl2 = new CountDownLatch(1);
final CountDownLatch cdl3 = new CountDownLatch(1);
List<Runnable> list = new ArrayList<Runnable>();
list.add(new Runnable() {
public void run() {
System.out.println("Task 1");
// inform that task 1 is finished
cdl1.countDown();
}
});
list.add(new Runnable() {
public void run() {
// wait until task 1 is finished
try {
cdl1.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Task 2");
// inform that task 2 is finished
cdl2.countDown();
}
});
list.add(new Runnable() {
public void run() {
// wait until task 2 is finished
try {
cdl2.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Task 3");
// inform that task 3 is finished
cdl3.countDown();
}
});
ExecutorService es = Executors.newFixedThreadPool(200);
for (int i = 0; i < 3; i++) {
es.submit(list.get(i));
}
es.shutdown();
es.awaitTermination(1, TimeUnit.MINUTES);
}
}
Another option is to create your own executor, call it OrderedExecutor, and create an array of encapsulated ThreadPoolExecutor objects, with 1 thread per internal executor. You then supply a mechanism for choosing one of the internal objects, eg, you can do this by providing an interface that the user of your class can implement:
executor = new OrderedExecutor( 10 /* pool size */, new OrderedExecutor.Chooser() {
public int choose( Runnable runnable ) {
MyRunnable myRunnable = (MyRunnable)runnable;
return myRunnable.someId();
});
executor.execute( new MyRunnable() );
The implementation of OrderedExecutor.execute() will then use the Chooser to get an int, you mod this with the pool size, and that's your index into the internal array. The idea being that "someId()" will return the same value for all the "a's", etc.
I created an OrderingExecutor for this problem. If you pass the same key to to method execute() with different runnables, the execution of the runnables with the same key will be in the order the execute() is called and will never overlap.
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Executor;
/**
* Special executor which can order the tasks if a common key is given.
* Runnables submitted with non-null key will guaranteed to run in order for the same key.
*
*/
public class OrderedExecutor {
private static final Queue<Runnable> EMPTY_QUEUE = new QueueWithHashCodeAndEquals<Runnable>(
new ConcurrentLinkedQueue<Runnable>());
private ConcurrentMap<Object, Queue<Runnable>> taskMap = new ConcurrentHashMap<Object, Queue<Runnable>>();
private Executor delegate;
private volatile boolean stopped;
public OrderedExecutor(Executor delegate) {
this.delegate = delegate;
}
public void execute(Runnable runnable, Object key) {
if (stopped) {
return;
}
if (key == null) {
delegate.execute(runnable);
return;
}
Queue<Runnable> queueForKey = taskMap.computeIfPresent(key, (k, v) -> {
v.add(runnable);
return v;
});
if (queueForKey == null) {
// There was no running task with this key
Queue<Runnable> newQ = new QueueWithHashCodeAndEquals<Runnable>(new ConcurrentLinkedQueue<Runnable>());
newQ.add(runnable);
// Use putIfAbsent because this execute() method can be called concurrently as well
queueForKey = taskMap.putIfAbsent(key, newQ);
if (queueForKey != null)
queueForKey.add(runnable);
delegate.execute(new InternalRunnable(key));
}
}
public void shutdown() {
stopped = true;
taskMap.clear();
}
/**
* Own Runnable used by OrderedExecutor.
* The runnable is associated with a specific key - the Queue<Runnable> for this
* key is polled.
* If the queue is empty, it tries to remove the queue from taskMap.
*
*/
private class InternalRunnable implements Runnable {
private Object key;
public InternalRunnable(Object key) {
this.key = key;
}
#Override
public void run() {
while (true) {
// There must be at least one task now
Runnable r = taskMap.get(key).poll();
while (r != null) {
r.run();
r = taskMap.get(key).poll();
}
// The queue emptied
// Remove from the map if and only if the queue is really empty
boolean removed = taskMap.remove(key, EMPTY_QUEUE);
if (removed) {
// The queue has been removed from the map,
// if a new task arrives with the same key, a new InternalRunnable
// will be created
break;
} // If the queue has not been removed from the map it means that someone put a task into it
// so we can safely continue the loop
}
}
}
/**
* Special Queue implementation, with equals() and hashCode() methods.
* By default, Java SE queues use identity equals() and default hashCode() methods.
* This implementation uses Arrays.equals(Queue::toArray()) and Arrays.hashCode(Queue::toArray()).
*
* #param <E> The type of elements in the queue.
*/
private static class QueueWithHashCodeAndEquals<E> implements Queue<E> {
private Queue<E> delegate;
public QueueWithHashCodeAndEquals(Queue<E> delegate) {
this.delegate = delegate;
}
public boolean add(E e) {
return delegate.add(e);
}
public boolean offer(E e) {
return delegate.offer(e);
}
public int size() {
return delegate.size();
}
public boolean isEmpty() {
return delegate.isEmpty();
}
public boolean contains(Object o) {
return delegate.contains(o);
}
public E remove() {
return delegate.remove();
}
public E poll() {
return delegate.poll();
}
public E element() {
return delegate.element();
}
public Iterator<E> iterator() {
return delegate.iterator();
}
public E peek() {
return delegate.peek();
}
public Object[] toArray() {
return delegate.toArray();
}
public <T> T[] toArray(T[] a) {
return delegate.toArray(a);
}
public boolean remove(Object o) {
return delegate.remove(o);
}
public boolean containsAll(Collection<?> c) {
return delegate.containsAll(c);
}
public boolean addAll(Collection<? extends E> c) {
return delegate.addAll(c);
}
public boolean removeAll(Collection<?> c) {
return delegate.removeAll(c);
}
public boolean retainAll(Collection<?> c) {
return delegate.retainAll(c);
}
public void clear() {
delegate.clear();
}
#Override
public boolean equals(Object obj) {
if (!(obj instanceof QueueWithHashCodeAndEquals)) {
return false;
}
QueueWithHashCodeAndEquals<?> other = (QueueWithHashCodeAndEquals<?>) obj;
return Arrays.equals(toArray(), other.toArray());
}
#Override
public int hashCode() {
return Arrays.hashCode(toArray());
}
}
}
In Habanero-Java library, there is a concept of data-driven tasks which can be used to express dependencies between tasks and avoid thread-blocking operations. Under the covers Habanero-Java library uses the JDKs ForkJoinPool (i.e. an ExecutorService).
For example, your use case for tasks A1, A2, A3, ... could be expressed as follows:
HjFuture a1 = future(() -> { doA1(); return true; });
HjFuture a2 = futureAwait(a1, () -> { doA2(); return true; });
HjFuture a3 = futureAwait(a2, () -> { doA3(); return true; });
Note that a1, a2, and a3 are just references to objects of type HjFuture and can be maintained in your custom data structures to specify the dependencies as and when the tasks A2 and A3 come in at runtime.
There are some tutorial slides available.
You can find further documentation as javadoc, API summary and primers.
I have written my won executor service which is sequence aware. It sequences the tasks which contain certain related reference and currently inflight.
You can go through the implementation at https://github.com/nenapu/SequenceAwareExecutorService

Categories

Resources