HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMajor

Run different methods in background threads without duplication

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
withoutbackgroundthreadsduplicationmethodsdifferentrun

Problem

In my Android app I have number of methods that should be executed in a background thread.

One of the methods looks like this

public static void processItem(final Context context, final String itemId)
{
    if (Looper.myLooper() == Looper.getMainLooper())
    {
        Thread task = new Thread()
        {
            @Override
            public void run()
            {
                processItem(context, playlistId);
            }
        };

        task.start();
        return;
    }

    // actual processing
}


As you can see, there are some code that only ensures an eligible thread is used.

How can I avoid copying this "threading" code over and over for each method that should be run in a background thread?

Solution

Extending Thread is an 'anti-pattern' in Java. The right way to do this work is to create an instance of a Runnable, and use the runnable as a constructor to a Thread instance.

Thread t = new Thread(new Runnable() {
    public void run() {
        /*
         * Do something
         */
    }
});

t.start();


But, and this is a big "but", in Java, in general, the practice of creating and using threads like this is being replaced by frameworks that manage the threads in a better way. In regular Java, you should be using the Executor, ExecutorService, and Executors class in the concurrent package.

As for android-specific use cases, you should read up on the threading models in Android paying special attention to the AsyncTask in Android dev kit

Update: more about the Thread anti-pattern

Jon Skeet says so ... ;-) and most people agree. What you have is something that needs to be done. That is what you need to implement, the way to do it. The place to run that something is on a thread. You do not implement the thread, you implement the task. There are two different concepts here: what needs to be done, and where it needs to be done. You are only implementing one of those.

Update: alternative solution

To reduce the logic required for managing the thread the code runs on, I would do one of two things:

  • simply always use a different thread. Simply remove the if-condition and do all the processing in a Runnable's run method.



-
Have a common utility method that looks something like:

private static final ExecutorService THREADPOOL = Executors.cachedThreadPool();

public static void runButNotOn(Runnable toRun, Thread notOn) {
    if (Thread.currentThread() == notOn) {
        THREADPOOL.submit(toRun);
    } else {
        toRun.run();
    }
}


and then you can call it in your method with:

private static void processImplementation(final Context context, final String itemId) {
     // ... the actual work.
}

public static void processItem(final Context context, final String itemId) {
    Runnable task = new Runnable(){
        public void run() {
            processImplementation(context, itemId);
        }
    };
    runButNotOn(task, Looper.getMainLooper().getThread());
}

Code Snippets

Thread t = new Thread(new Runnable() {
    public void run() {
        /*
         * Do something
         */
    }
});

t.start();
private static final ExecutorService THREADPOOL = Executors.cachedThreadPool();

public static void runButNotOn(Runnable toRun, Thread notOn) {
    if (Thread.currentThread() == notOn) {
        THREADPOOL.submit(toRun);
    } else {
        toRun.run();
    }
}
private static void processImplementation(final Context context, final String itemId) {
     // ... the actual work.
}

public static void processItem(final Context context, final String itemId) {
    Runnable task = new Runnable(){
        public void run() {
            processImplementation(context, itemId);
        }
    };
    runButNotOn(task, Looper.getMainLooper().getThread());
}

Context

StackExchange Code Review Q#56428, answer score: 21

Revisions (0)

No revisions yet.