IntentService Concurrency - java

I have got a class that extends IntentService, let's say class A, and then I have got 2 more classes as class B and class C, these classes extends class A. The reason is because I want to initialize everything in class A so that code would be reused in class B and C. So class B and C's onHandleIntent method looks like:
#Override
protected void onHandleIntent(Intent intent) {
super.onHandleIntent(intent);
//Specific init stuff
}
What I want to do is simply do some concurrency checks at class A's either constructor or onHandleIntent. For example when method x is being used(doesn't matter which class uses it) I would like to be able to flag this method being used. Sometimes one method schedules another thread by using Handler.postDelayed, so I want to make sure that flag is kept as in use until the thead work is finished.
So far it sounds like it can be done easily by shared singleton, however each of these classes have their own AlarmManager which extends BroadcastReceiver, so using a shared singleton doesn't really work as lifecycle existence of a singleton is not guaranteed.
The only solution that I can think of is using a database or local file system, which sounds quite silly. So is there another way to flag concurrent methods among different IntentService that are being triggered by AlarmManager?
To give a clear image I'd like to give an example of class A, class B and class C
public class A extends IntentService {
public A(String name) {
super(name);
//initialise objects here
}
#Override
protected void onHandleIntent(Intent intent) {
//initialise objects that uses intent here
}
protected synchronized void methodA() {
//wait until flagB is free
flagA = in_use; //Flag something as being in use here
//change some objects here
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//do some stuff with objects
flagB = not_in_use; //Flag something as being free here
}
}, (1000 * 45));// 45secs
}
protected synchronized void methodB() {
if (flagA == not_in_use) {
flagB = in_use;
//do some stuff with objects
flagB = not_in_use;
}
else {
//do something else
}
}
public class B extends IntentService {
public A(String name) {
super("B");//Super initializes everything
}
#Override
protected void onHandleIntent(Intent intent) {//This will run every 30 minutes
super.onHandleIntent(intent);
methodA();
}
}
public class C extends IntentService {
public A(String name) {
super("C");//Super initializes everything
}
#Override
protected void onHandleIntent(Intent intent) {//This will run every 45 minutes
super.onHandleIntent(intent);
methodB();
}
}
So basically class B and C doesn't contain any private classes. What i want to do is just like the example above, flag things.
The problem is as I mentioned if it is just a static field, then static field might not stay in the memory as Android OS can kill anything inactive for saving memory.

What I want to do is simply do some concurrency checks at class A's either constructor
Don't block in a constructor. Creating an object should be a free operation. In case of IntentService you would probably get an ANR because the object is constructed from within the main thread.
or onHandleIntent
Yes. That would be a place where you could do that because that's where something actually happens. And it is executed within a background thread so blocking here is ok.
To synchronize between multiple instances of a class (including subclasses) you will need to use something static because that's the only common thing that multiple instances "share".
Synchronizing outside of the lifetime of your app is also (probably) not required. If your app process is killed and restarted from AlarmManager you would have a new singleton to work with. Anything that happened before is dead and so nothing can happen in parallel.
For example synchronize using the .class object of A
public class AService extends IntentService {
public AService() {
super("AService");
}
#Override
protected void onHandleIntent(Intent intent) {
synchronized (AService.class) {
// magic happens here.
}
}
}
class BService extends AService {
void foo() {
synchronized(AService.class) {
// we can't be in here if another intentservice is within above block.
}
}
}
That does work as long as those services are running within the same app process (i.e. every simple app that does not define extra processes). static is globally accessible everywhere in the app.
External locking using e.g. the filesystem would be required if you have multiple processes since they can't access each other's objects at all.
besides synchronized, look into java.util.concurrent for more powerful / better ways of synchronizing. E.g. `Semaphore and ReentrantLock (roughly equivalent to synchronized)
I want to make sure that flag is kept as in use until the thead work is finished.
If you app is killed, you'll have to restart the work if it did not finish. So keeping a "work-progress-flag" beyond the lifetime of your app makes no sense. And static (e.g. your singleton) works fine while it is running.

Related

Best practices for start() and stop() in Android MVP?

I have some questions regarding the Presenter’s start(), stop() method. What would you normally put into these methods to prevent memory leaks or any potential problem.
For example, I have an Activity that host a VideoView. The videoPath passed to the Activity will be passed to the Presenter to a VideoUtility to trim the original video into a shorter one before getting passed back to the Activity to be played with the VideoView.
Here’s the confusion: I don’t know where is the appropriate place to call the trimVideo() method as it essentially only need to happen once (unlike in the Android Architect Blueprint, the task is updated with latest data, and thus it’s put in the onResume()).
Please see the code snippet below:
VideoEditorContract:
public interface VideoEditorContract {
interface View extends BaseView<Presenter> {
void playTrimVideo(String trimmedVideoPath);
}
interface Presenter extends BasePresenter {
}
}
VideoEditorActivityBase:
public class VideoEditorActivityBase extends AppCompatActivity implements VideoEditorContract.View {
private VideoEditorContract.Presenter mPresenter;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_editor);
String videoPath = getIntent().getStringExtra(RequestCode.EXTRA_VIDEO_PATH);
mPresenter = new VideoEditorPresenter(videoPath, this);
}
#Override
public void onResume(){
super.onResume();
mPresenter.start();
}
#Override
public void playTrimVideo(String trimmedVideoPath) {
final VideoView vv = findViewById(R.id.act_video_editor_videoView);
vv.setVideoPath(trimmedVideoPath);
vv.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
vv.start();
}
});
}
#Override
public void setPresenter(VideoEditorContract.Presenter presenter) {
//do nothing as this activity has already init a presenter
}
}
VideoEditorPresenter:
public class VideoEditorPresenter implements VideoEditorContract.Presenter {
private final VideoEditorContract.View mVideoEditorView;
#NonNull
private String mVideoPath;
public VideoEditorPresenter(#NonNull String videoPath, #NonNull VideoEditorContract.View videoEditorView) {
mVideoPath = checkNotNull(videoPath);
mVideoEditorView = checkNotNull(videoEditorView, "videoEditorView cannot be null!");
mVideoEditorView.setPresenter(this);
//trimVideo(); //should I do it here since this task is only need to be done once
}
#Override
public void start() {
//trimVideo(); //I can do it here but then I need to introduce a control variable; not sure if this is the best practice
}
private void trimVideo() {
//trim video stuff
}
// Currently it doesn't have a stop() method. But if it have one,
// what should I put in it? Releasing and clean up the
// VideoUtility I suppose?
}
I got the answer from Francesco Cervone in Medium about this matter (his article is also an excellent resource on MVP, btw. Very well in tune with the Android Architect Blueprint). I leave the relevant bit here for future reader.
Hi, thank you.
Well, I think that the video should be trimmed in the Presenter#start(). Then, after the video has been trimmed, the presenter should call view.playTrimmedVideo(). You shouldn’t do anything in the presenter constructor.
I suppose the video “editing” is something expensive, so you should do that in a separate thread (using for example an async task). You need to implement the Presenter#stop() method because you have to cancel ongoing operations if there are any, unless you retain the presenter.
You said that the trimVideo should be called just once. You could cache/persist in some way the result of trimVideo so that if the video has been already trimmed, you use it.
I hope I answered your question.
"Could you elaborate more on why shouldn’t we put anything in the Presenter’s constructor? I’ve seen the Presenter’s bare minimal constructor in a couple of places but I don’t understand the reason behind it."
First, it’s a responsibility problem: you are going to create an instance of Presenter, and I don’t think that the video editing is something that belongs to the construction of that object.
Second, you don’t know when the presenter is being instantiated, so you shouldn’t execute expensive tasks in the constructor. If you use some dependency injection framework, the construction of the Presenter would be managed by the framework itself and it needs to be efficient. The construction of other objects could depend on the presenter one.

Android Redirection (delegates pointers)

I would like to call different code (callbacks) from within a background thread loop and use that background thread to perform the work. It would be similar to delegates in C#.
public class test {
private boolean keepRunning;
private boolean messageReady;
private MyClass myClass;
void LongBackgroundWork(){
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
while (keepRunning) {
if (messageReady){
myClass.callback(); // call different methods here
// to be decided at runtime and run on this worker thread
}
}
}
});
thread.start();
}
}
I want to use the background thread not the UI thread. I want to set a callback from within myClass to choose what code is called. It's easy in C# how to do it Java.
I don't have much experience in Java and don't understand what mechanism to use. Should I be using a handler? Can a handler run code on a background thread?
I'd wager you want to have a pattern where an event or some occurence happens and you need to initiate a code block somewhere.
A pattern that could help you is perhaps an Observer Wiki and firing off to the event. You can also check out this SO question here if you'd like: Delegate vs Callback in Java
In your case, I think you'd want to have someone handle the responsibility of what you have to do when a message is ready. So what you're looking for is someone to perform the action, once the event is read (message ready).
Take for example Class Foo is your container of listeners, or also called an Observer that will be notified of any events. You can have a list of callbacks here to some object that is responsible for your logic to do what you need to do next.
Then you would have an Observable object or a class that would implement some logic when notified. You could then have various class objects perform the necessary logic by implementing the callback function required.
Example:
// Observer
public class Foo {
// List of objects that implement Callbacks interface
private List<Callbacks> mList;
public Foo() {
// Initialize here
}
public void addListener(Callbacks cb) {
mList.add(cb);
}
public void notifyListeners() {
for ( Callback cb : mList) {
cb.onCallback();
}
}
// Public interface to be implemented by users
public interface Callback {
void onCallback();
}
}
Then just have a class implement this object and you can pass it along if you'd like.
// Bar implements Foo.Callback interface
public class Bar implements Foo.Callback {
public class Bar() {}
#Override
public void onCallback() {
// Perform logic here
}
}
Finally in your code, you'd just create the Foo object, add a listener, and notify them when it's time to fire your event.
if i understood you properly,you cant do this on UI thread, basically when android see Thread like this it will expect that it's a long operation however you can call it by AsyncTask or Handler
you can make something like this
private class MyAsyncTask extends AsyncTask<Void,Void,Void>{
protected Void doInBackground() {
MyClass myClass=new MyClass();
myClass.LongBackgroundWork();
}
return totalSize;
}
}
this is how yo can call your thread otherwise you have to use Handler instead
Handler handler=new Handler();
handler.post(new Runnable(){
MyClass myClass=new MyClass();
myClass.LongBackgroundWork();
})

Setting ThreadContext for all threads in application

From this answer https://stackoverflow.com/a/25125159/4367326 I have routingAppender working but I want to set the ThreadContext for every thread in the program.
When I set
ThreadContext.put("logFileName", "TestLogFile");
it works for the main thread and logs as expected but not for any other threads in my application. How can I achieve this?
Every child thread will inherit fathers ThreadContext state if you set up system property isThreadContextMapInheritable to true. But this will not work for Executors so you need to manually copy data from one thread to another.
Update#2
You can do something like this:
public abstract class ThreadContextRunnable implements Runnable {
private final Map context = ThreadContext.getContext();
#Override
public final void run() {
if (context != null) {
ThreadContext.putAll(context);
}
try {
runWithContext();
} finally {
ThreadContext.clearAll();
}
}
protected abstract void runWithContext();
}
And then you only need to implement runWithContext method.

Who should implement the concurrency - the client or the server

In my application I have the following potentially long running classes:
ScheduleLocalNotificationsOperation
UnScheduleLocalNotificationsOperation
SyncEventsToDeviceCalendarOperation
UnSyncEventsToDeviceCalendarOperation
SaveProductsToLocalStorageImpl
and so on.
Most of these are structured this way:
public interface Operation {
void execute();
}
public class ScheduleLocalNotificationsOperation implements Operation {
private MyApplication application;
private List<LocalNotificationDescriptor> localNotifications;
public ScheduleLocalNotificationsOperation (MyApplication application, List<LocalNotificationDescriptor> localNotifications) {
this.application = application;
this.localNotifications = localNotifications;
}
#Override
public void execute() {
// Do some stuff
}
}
Ideally, I would like to design my Operation classes to be concurrency agnostic, and to be able to impose some multithreading policy on them from the outside, like so:
public class MainActivity extends Activity {
public static ExecutorService executorService = Executors.newCachedThreadPool();
#Override
public void onCreate() {
executorService.submit(new Runnable {
#Override
public void run() {
new ScheduleLocalNotificationsOperation(application, createLocalNotificationsList()).execute();
}
});
}
}
But this way I should implement some concurrency policy in every client, every time I call those classes.
On the other hand, I dont want to interrupt the pure logic in those operations by adding concurrency to them, so my question is basically, from design stand point what is the better way to do this, if there is a clearly defined one?
Can I create an OperationsRunner class that will be called by any client and will execute any Operation using polymorphism and make that class be the only one that deals with concurrency?

How to have a shared context per top-level process/thread without using InheritableThreadLocal?

I'd like to see if there's a good pattern for sharing a context across all classes and subthreads of a top-level thread without using InheritableThreadLocal.
I've got several top-level processes that each run in their own thread. These top-level processes often spawn temporary subthreads.
I want each top level process to have and manage it's own database connection.
I do not want to pass around the database connection from class to class and from thread to subthread (my associate calls this the "community bicycle" pattern). These are big top-level processes and it would mean editing probably hundreds of method signatures to pass around this database connection.
Right now I call a singleton to get the database connection manager. The singleton uses InheritableThreadLocal so that each top-level process has it's own version of it. While I know some people have problems with singletons, it means I can just say DBConnector.getDBConnection(args) (to paraphrase) whenever I need the correctly managed connection. I am not tied to this method if I can find a better and yet still-clean solution.
For various reasons InheritableThreadLocal is proving to be tricky. (See this question.)
Does anyone have a suggestion to handle this kind of thing that doesn't require either InheritableThreadLocal or passing around some context object all over the place?
Thanks for any help!
Update: I've managed to solve the immediate problem (see the linked question) but I'd still like to hear about other possible approaches. forty-two's suggestion below is good and does work (thanks!), but see the comments for why it's problematic. If people vote for jtahlborn's answer and tell me that I'm being obsessive for wanting to avoid passing around my database connection then I will relent, select that as my answer, and revise my world-view.
I haven't tested this, but the idea is to create a customized ThreadPoolExecutor that knows how to get the context object and use #beforeExecute() to transfer the context object to the thread that is going to execute the task. To be a nice citizen, you should also clear the context object in #afterEXecute(), but I leave that as an exercise.
public class XyzThreadPoolExecutor extends ThreadPoolExecutor {
public XyzThreadPoolExecutor() {
super(3, 3, 100, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), new MyThreadFactory());
}
#Override
public void execute(Runnable command) {
/*
* get the context object from the calling thread
*/
Object context = null;
super.execute(new MyRunnable(context, command));
}
#Override
protected void beforeExecute(Thread t, Runnable r) {
((MyRunnable)r).updateThreadLocal((MyThread) t);
super.beforeExecute(t, r);
}
private static class MyThreadFactory implements ThreadFactory {
#Override
public Thread newThread(Runnable r) {
return new MyThread(r);
}
}
private class MyRunnable implements Runnable {
private final Object context;
private final Runnable delegate;
public MyRunnable(Object context, Runnable delegate) {
super();
this.context = context;
this.delegate = delegate;
}
void updateThreadLocal(MyThread thread) {
thread.setContext(context);
}
#Override
public void run() {
delegate.run();
}
}
private static class MyThread extends Thread {
public MyThread(Runnable target) {
super(target);
}
public void setContext(Object context) {
// set the context object here using thread local
}
}
}
the "community bicycle" solution (as you call it) is actually much better than the global (or pseudo global) singleton that you are currently using. it makes the code testable and it makes it very easy to choose which classes use which context. if done well, you don't need to add the context object to every method signature. you generally ensure that all the "major" classes have a reference to the current context, and that any "minor" classes have access to the relevant "major" class. one-off methods which may need access to the context will need their method signatures updated, but most classes should have the context available through a member variable.
As a ThreadLocal is essentially a Map keyed on your thread, couldn't you implement a Map keyed on your thread name? All you then need is an effective naming strategy that meets your requirements.
As a Lisper, I very much agree with your worldview and would consider it a shame if you were to revise it. :-)
If it were me, I would simply use a ThreadGroup for each top-level process, and associate each connection with the group the caller is running in. If using in conjunction with thread pools, just ensure the pools use threads in the correct thread group (for instance, by having a pool per thread group).
Example implementation:
public class CachedConnection {
/* Whatever */
}
public class ProcessContext extends ThreadGroup {
private static final Map<ProcessContext, Map<Class, Object>> contexts = new WeakHashMap<ProcessContext, Map<Class, Object>>();
public static T getContext(Class<T> cls) {
ProcessContext tg = currentContext();
Map<Class, Object> ctx;
synchronized(contexts) {
if((ctx = contexts.get(tg)) == null)
contexts.put(tg, ctx = new HashMap<Class, Object>());
}
synchronized(ctx) {
Object cur = ctx.get(cls);
if(cur != null)
return(cls.cast(cur));
T new_t;
try {
new_t = cls.newInstance();
} catch(Exception e) {
throw(new RuntimeException(e));
}
ctx.put(cls, new_t);
return(new_t);
}
}
public static ProcessContext currentContext() {
ThreadGroup tg = Thread.currentThread().getThreadGroup();
while(true) {
if(tg instanceof ProcessContext)
return((ProcessContext)tg);
tg = tg.getParent();
if(tg == null)
throw(new IllegalStateException("Not running in a ProcessContext"));
}
}
}
If you then simply make sure to run all your threads in a proper ProcessContext, you can get a CachedConnection anywhere by calling ProcessContext.getContext(CachedConnection.class).
Of course, as mentioned above, you would have to make sure that any other threads you may delegate work to also run in the correct ProcessContext, but I'm pretty sure that problem is inherent in your description -- you would obviously need to specify somehow which one of multiple contexts your delegation workers run in. If anything, it could be conceivable to modify ProcessContext as follows:
public class ProcessContext extends ThreadGroup {
/* getContext() as above */
private static final ThreadLocal<ProcessContext> tempctx = new ThreadLocal<ProcessContext>();
public static ProcessContext currentContext() {
if(tempctx.get() != null)
return(tempctx.get());
ThreadGroup tg = Thread.currentThread().getThreadGroup();
while(true) {
if(tg instanceof ProcessContext)
return((ProcessContext)tg);
tg = tg.getParent();
if(tg == null)
throw(new IllegalStateException("Not running in a ProcessContext"));
}
}
public class RunnableInContext implements Runnable {
private final Runnable delegate;
public RunnableInContext(Runnable delegate) {this.delegate = delegate;}
public void run() {
ProcessContext old = tempctx.get();
tempctx.set(ProcessContext.this);
try {
delegate.run();
} finally {
tempctx.set(old);
}
}
}
public static Runnable wrapInContext(Runnable delegate) {
return(currentContext().new RunnableInContext(delegate));
}
}
That way, you could use ProcessContext.wrapInContext() to pass a Runnable which, when run, inherits its context from where it was created.
(Note that I haven't actually tried the above code, so it may well be full of typos.)
I would not support your world-view and jthalborn's idea on the count that its more testable even.
Though paraphrasing first what I have understood from your problme statement is like this.
There are 3 or 4 top-level processes (and they are basically having a thread of their own). And connection object is what is diffrenet in them.
You need some basic characteristic of Connection to be set up and done once.
The child threads in no way change the Connection object passe to them from top-level threads.
Here is what I propose, you do need the one tim,e set-up of you Connection but then in each of your top-level process, you do 1) further processing of that Connection 2) keep a InheriatbleThreadLocal (and the child process of your top-level thread will have the modified connection object. 3) Pass these threasd implementing classes. MyThread1, MyThread2, MyThread3, ... MyThread4 in the Executor. (This is different from the other linked question of yours that if you need some gating, Semaphore is a better approach)
Why I said that its not less testable than jthalborn's view is that in that case also you anyway again needs to provide mocked Connection object. Here too. Plus conecptually passing the object and keeping the object in ThreadLocal is one and the same (InheritableThreadLocal is a map which gets passed by java inbuilt way, nothing bad here I believe).
EDIT: I did keep in account that its a closed system and we are not having "free" threads tempring with connection

Categories