Clean Inner Class implementing Runnable - java

I have got a Class for a CustomView that has to inner Classes, both implement Runnable to do a Job in a separate Thread.
public class ValueSelector extends LinearLayout{
.....
private class AutoIncrementer implements Runnable {
#Override
public void run() {
if (plusButtonIsPressed) {
incrementValue();
mHandler.postDelayed(new AutoIncrementer(), REPEAT_INTERVAL_MS);
} else {
mHandler.removeCallbacks(this);
Thread.currentThread().interrupt();
}
}
}
private class AutoDecrementer implements Runnable {
#Override
public void run() {
if (minusButtonIsPressed) {
decrementValue();
mHandler.postDelayed(new AutoDecrementer(), REPEAT_INTERVAL_MS);
} else {
mHandler.removeCallbacks(this);
Thread.currentThread().interrupt();
}
}
}
}
How to clean them up properly?
Do they get Destroyed automatically when the Activity hosting those CustomViews gets destroyed?
Cheers

It will not get destroyed causing a memory leak, as your thread will have a strong reference to your view, and hence your activity.
Make the inner class static and hold weak reference to variables you need in run method.
Second thing you can do is interrupt your thread , when you view get detached from the window and have check in the run method if thread got interrupted or not, though not necessary if your thread is not doing too much work.
Here is what your runnable should look like
private static class AutoDecrementer implements Runnable {
AutoDecrementer (ValueSelector valueSelector ){
this.weakRef = new WeakReference<>(valueSelector);
}
#Override
public void run() {
ValueSelector valueSelector = (ValueSelector )weakRef.get();
if(valueSelector == null){
return ;
}
if (valueSelector.minusButtonIsPressed) {
valueSelector .decrementValue();
valueSelector .mHandler.postDelayed(new AutoDecrementer(), REPEAT_INTERVAL_MS);
} else {
valueSelector.mHandler.removeCallbacks(this);
Thread.currentThread().interrupt();
}
}
}
I have not checked for any errors.

No, it will cause error if Activity is destroyed while timer event is still pending. To avoied that, use WeakReference to some object, decrementing value.
But, generally it is bad practice - to mix UI and some ligic, because it is difficule to test. Consider using rxJava library, this will look like
Subscriptioin s = Observable.just(100, TimeUnit.Milliseconds)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.computation())
.subscribe(t -> decrementValue());
in your onPause() method cancel that actioin by
if (s != null && !s.inUnsubscribed()) {
s.unsubscribe();
s = null;
}

Related

Thread field inside a class that implements Runnable, which instantiates said class

In my school's program solutions for multithreading problems and exercises, classes that implement the Runnable interface are usually given a Thread field, which is automatically instantiated in the following example:
protected Thread thr = new Thread(this);
This field is subsequently used as a means of controlling the Thread over which the class itself is instantiated. For example:
public void stop() {
if (thr != null) thr.interrupt();
}
Which is then used to interrupt Thread objects made with the Runnable class.
A full class example, ported directly from an aforementioned solution, is given below:
package hokej;
import java.awt.Color;
public abstract class AktFigura extends Figura implements Runnable {
protected Thread nit = new Thread(this);
private int tAzur;
private boolean radi;
public AktFigura(Scena s, int xx, int yy,
Color b, int t) {
super(s, xx, yy, b); tAzur = t;
}
protected abstract void azurirajPolozaj();
public void run() {
try {
while (!Thread.interrupted()) {
synchronized (this) {
if (!radi) wait();
}
azurirajPolozaj();
scena.repaint();
Thread.sleep(tAzur);
}
} catch (InterruptedException ie) {}
}
public synchronized void kreni() {
radi = true; notify();
}
public void stani() { radi = false; }
public void prekini() {
if (nit != null) nit.interrupt();
}
}
My question is this: How does this work?
Shouldn't the Thread field be a separate object from the object made by calling new Thread(class); in other parts of the program (hence the keyword's name - new)?
Or is this simply a special case that the Java interpreter recognizes in a certain way?
Another question would be the viability of this design as a control method. Is there any simpler/more efficient alternative for controlling a Runnable's thread?
How does this work?
The Thread constructor takes a Runnable, Thread implements this interface. this refers to a Thread instance. So, the statement Thread thr = new Thread(this) is valid, but this practice should be avoided.
Is there any simpler/more efficient alternative for controlling a Runnable's thread?
Thread thread = new Thread(new AktFiguraImpl());
thread.start();
You could control a thread by a class specifically designed for that purpose.
class ThreadController {
public ThreadController(Thread thread, AktFigura figura) { ... }
// methods to manipulate the thread
}

is this a correct way to use Java FutureTask & Callable?

I'm implementing a layer to wrap a 3rd party communication layer.
The contract I need to implement is:
FutureTask<SomeData> send(Request request);
My layer has an onMessageReceived method, which is called by the 3rd party when a response arrives.
The approach I've taken to implement my layer is as follows:
I have a callable, which waits on a condition with a timeout:
interface MyCallable<T> extends Callable<T> {
void signal();
}
class CallableWithSignal<T> implements MyCallable<T> {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private long waitTime;
public CallableWithSignal(int waitTimeSeconds){
this.waitTime=waitTimeSeconds;
}
#Override
public T call() throws Exception {
lock.lock();
try {
boolean wasSignaled = condition.await(waitTime, TimeUnit.SECONDS);
if(wasSignaled)
return null;
System.out.println("throwing exeption");
throw new Exception("timeout");
} finally {
lock.unlock();
}
}
#Override
public void signal() {
lock.lock();
try {
condition.signal();
} finally {
lock.unlock();
}
}
}
I also have extended FutureTask to expose the set method, as follows:
class MyFutureTask<V> extends FutureTask<V> {
private MyCallable<V> myCallable;
public MyFutureTask(MyCallable<V> r) { super(r); myCallable = r;}
#Override
public void set(V x) { super.set(x); }
#Override
public void setException(Throwable t) { super.setException(t); }
#Override
protected void done() {
super.done();
myCallable.signal();
}
}
When the task is done, I signal the callable to stop it.
So every time a send is called, I create a new MyFutureTask, run it using an executor, save it in a map and return it.
When onMessageReceived is called I find the task in the map and set its result with the set method.
Is this a good approach?
And another question: is it a good approach to move the executor logic inside the task? I mean, to create a start method for it, which will run the task using the executor.
please advice.

Runnable/Thread possible misconception

Not sure I understand threads correctly, could someone tell me whether I´m right or wrong in the following example:
class Task {
String taskName;
private Thread thread;
boolean isFinished;
public Task(String name){
taskName = name;
}
public void createTask(final Runnable r) {
thread = new Thread(r){
public void run(){
if(r != null) {
r.run();
isFinished = true;
}
}
};
thread.start();
}
}
What I'm actually doing in my app is that I set the isFinished to true, and have an observer that whenever the isFinished is true does some stuff. I'm afraid that isFinished is set to true, before all code in the Runnable I pass as parameter is actually terminated.
Isn't the run method suppose to put the code I pass, in a separate thread and run that code asynchronously?
Close, but your new thread is already given the runnable object to execute. You really want to give it a wrapper which runs the r.run() method and then sets isFinished.
Change:
public void createTask(final Runnable r) {
thread = new Thread(r){
public void run(){
if(r != null) {
r.run();
isFinished = true;
}
}
};
thread.start();
}
to
public void createTask(final Runnable r) {
thread = new Thread( new Runnable {
public void run(){
if(r != null) {
r.run();
isFinished = true;
}
}
});
thread.start();
}
I would be remiss if I didn't point out the thread-unsafetiness of isFinished. You will not be guaranteed to notice when the thread finishes, without adding synchronization. I recommend you add:
public synchronized boolean getIsFinished()
{
return isFinished;
}
public synchronized void setIsFinished(boolean finished)
{
isFinished = finished;
}
And use these methods to get or set the isFinished flag.
Given your lack of synchronization here, you may be seeing other thread-safety oddities, depending on whether or not your r.run() method and your other "observer" are sharing data without synchronization as well.
You should almost never pass a Runnable into the constructor of a Thread and override the Thread's run() method.
The following two pieces of code are essentially identical:
Runnable r = new Runnable( )
{
public void run( )
{
// do stuff...
}
};
new Thread( r ).start( );
An here's another way to accomplish the same thing by overriding run():
(new Thread( )
{
public void run( )
{
// do stuff...
}
}).start( );
The way you wrote your code, isFinished will not be set to true until r.run() is complete. It may be appearing otherwise because you may have some data visibility issues due to missing synchronization or missing volatile declarations.
It's a little bit odd since you're both passing in the Runnable to the constructor, but calling it using the reference from your method declaration, not the one inside the thread. But it "works", there's just a redundancy there.
As an aside, don't forget #Override in your anonymous class :)
No, the run method simply is a normal function, that you can override when extending the Thread class in order to implement your own behaviour.
It's the start method of the Thread class that starts a new thread and runs that code async.
Well your code is partially right, and partially wrong.
You are correct that isFinished will only be set to true once everything inside the runnable you are passing in the parameter has finished executing.
However, due to the particular semantics of the java memory model (I'll get into more details about that below), it is possible that when you set isFinished to true, that change is only visible to the thread that has set that variable to true. If you want your code to work as expected, you need to declare isFinished as volatile. This will make any changes you make to that variable immediately visible by other threads.
Another way to do it is to declare isFinished as AtomicBoolean rather than boolean. This class has many methods that allow you to check and set the boolean in an atomic way, helping you to avoid many common multithreading pitfalls.
I suggest you use the synchronization primitive specifically designed for your problem.
This primitive is called CountDownLatch.
Here is the updated code:
class Task {
String taskName;
private Thread thread;
CountDownLatch finishedSignal = new CountDownLatch( 1 );
public Task(String name){
taskName = name;
}
public void createTask(final Runnable r) {
thread = new Thread(r){
public void run(){
if(r != null) {
r.run();
finishedSignal.countDown( );
}
}
};
thread.start();
finishedSignal.await( );
}
}
You should use a FutureTask instead of your own Task class. It has an isDone() method, and it is integrated nicely with the Executor framework.
Most importantly the happens-before relationships are maintained as you expect it (actually in your code the problem is not that isFinished is set to true, before all code in the Runnable is terminated, but the other way: possibly it will not be set to true in the original thread even if the Runnable is terminated)
Example:
Runnable runnable = new Runnable() {
#Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("work done");
}
};
FutureTask<Void> task = new FutureTask<Void>(runnable, null);
ExecutorService es = Executors.newSingleThreadExecutor();
es.submit (task);
while (!task.isDone()) {
System.out.println("waiting...");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

Android thread sometimes doesn't start

So I'm having problems with my threads in an Android project. I have a ThreadStarter class, with a BuildScreen() function, which actually creates the layout for each activity. The only problem is, sometimes the threads just won't start, and I have no idea why. They work like 98% of the time though, but when they don't, the current activity will never get initalized, and the user has to restart the app, which is inconvenient.
Here is a snippet of my code:
public class ThreadStarter
{
public static void BuildScreen()
{
try
{
GlobalVariables.screenDrawer.onStart();
GlobalVariables.listInitaliser.onStart();
Logger.log("ThreadStarter.BuildScreen", "Threads started");
}
catch(IllegalThreadStateException e)
{
GlobalVariables.screenDrawer.StopThread();
GlobalVariables.listInitaliser.StopThread();
Logger.log("ThreadStarter.BuildScreen", "Threads stopped");
GlobalVariables.screenDrawer.onStart();
GlobalVariables.listInitaliser.onStart();
}
catch(Exception e)
{
Logger.Error("Couldn't stop or start the threads!");
Logger.Error("Exception () Message: " + e.getMessage());
}
}
}
The threads:
public class ListInitialiser extends Thread
{
private static ListInitialiser _thread;
public synchronized void run()
{
GlobalVariables.CurrentActivity.UpdateLists();
}
public void onStart()
{
_thread = new ListInitialiser();
_thread.start();
}
public void StopThread()
{
if (_thread != null)
{
_thread.interrupt();
_thread = null;
}
}
}
I won't insert the ScreenDrawer thread here, because it's pretty much the same, except it calls another function.
And this is how every activity is created (of course the contentView differs in each file):
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
getWindow().getAttributes().windowAnimations = R.style.Fade;
setContentView(R.layout.activity_fine_data_3);
GlobalVariables.CurrentActivity = this;
ThreadStarter.BuildScreen();
Logger.log("INFORMATION", "Person3DataActivity (Information 3/5)");
}
In the GlobalVariables section I have these variables:
public static ScreenDrawer screenDrawer = new ScreenDrawer();
public static ListInitialiser listInitaliser = new ListInitialiser();
If anyone has a solution or and idea, please share it with me.
Thanks in advance.
EDIT: Okay, so I took onof's (rather harsh but useful :)) advice, and refactored my code to use AsyncTask instead. It seems to be working pretty fine. I managed to implement it into my AbstractActivity class, which is the parent of every Activity I use, and now all I have to do is call BuildScreen() method in every onCreate method.
Thanks for the replies everyone.
try to add this to your class where u declared Global Variables
private static ListInitialiser instance;
public static synchronized ListInitialiser getInstance() {
if (instance == null)
instance = new ListInitialiser();
return instance;
}
Everytime you donot have to create new when u r taking static.I dont know but may be this can help
You can't rely on static variables as everything that is static (non final) in Android can be cleared any time the system need memory. So don't think static = storage.
You should instead instantiate the objects when you need them, like following:
public static ScreenDrawer getScreenDrawer() {
return new ScreenDrawer();
}
public static ListInitialiser getListInitialiser () {
return new ListInitialiser ();
}

How to notify all observers without holding the thread?

I have a thread inside a class like this-
import java.util.Observable;
public class Download extends Observable {
private int state = 0;
private final Thread myThread = new Thread(() -> {
/*
some work to do here
*/
setChanged();
notifyObservers(state);
});
public void download(int state) {
if (!myThread.isAlive()) {
this.state = state;
myThread.start();
}
}
public Thread getThread() {
return myThread;
}
public static void MyMethod() throws InterruptedException {
Download down = new Download();
down.addObserver((Observable ob, Object dat) -> {
System.out.println(ob);
if ((int) dat == 1) {
down.download(2);
} else {
System.out.println("success");
}
});
down.download(1);
down.getThread().join();
}
public static void main() throws InterruptedException {
MyMethod();
}
}
The problem is I never get it to print the "success" message.
I assume, it is because all observers are being notified from inside of MyThread. So when down.download(2) is called from the observer inside MyMethod(), the previous thread is still running and the call is ignored.
How can I notify all observers from the main thread, not from the myThread?
You are calling down.download(2) from within the execution of MyThread, therefore the thread is still alive which means that your download method does nothing because of if(!myThread.isAlive()).
I would recommend you to use the Executor framework and Listenable Futures from Guava instead of creating threads manually. Example code from the Guava wiki:
ListeningExecutorService service =
MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
ListenableFuture<Explosion> explosion = service.submit(new Callable<Explosion>() {
public Explosion call() {
return pushBigRedButton();
}
});
Futures.addCallback(explosion, new FutureCallback<Explosion>() {
// we want this handler to run immediately after we push the big red button!
public void onSuccess(Explosion explosion) {
walkAwayFrom(explosion);
}
public void onFailure(Throwable thrown) {
battleArchNemesis(); // escaped the explosion!
}
});
Note that Futures.addCallback(..) also has an overload which allows you to determine which executor should execute the callback, this seems to be what you want.

Categories