1

In an android app that i am developing, I need to make an extra thread to handle some repetitive tasks. I only need one thread and the task is very simple but frequent, intermittent, and should be in order

I figured out Executors.newSingleThreadExecutor is a good way for these kinds of situations. However, I really don't get the benefit of using this over creating a new thread.

Instead of using Executors.newSingleThreadExecutor and using submit() function to queue tasks, is it bad to just make a dedicated thread? I will make it go through a queue of tasks and when the queue is empty it will wait() and when ever the main thread sends a new task it it will notify() the worker thread. Is this bad practice?

// loop for worker thread 
public class WorkerThrd extends Thread {

    public void run() { 
        while(true){

            while (!queue.empty()) {
                queue.getTask().doSth();
            }
            synchronized(this){
                try {
                    wait();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    } 
}

// from main thread 

private WorkerThread wthread;
public void initiation(){
    wthread = new WorkerThread();
    wthread.start();
}

public void postSth(){
    wthread.queue.post(new task()); // a thread safety queue 
    synchronized(wthread){
        if(wthread.getState() == Thread.State.WAITING) {
           wthread.notify();
        }
    }
}

P.S. though I assumed the queue is thread safety, should I need a synchronized block whenever I call wait() or notify() ?? even when only one thread will call wait() and one other thread will call notify() ?

NamHo Lee
  • 309
  • 3
  • 13
  • What if the thread isn't waiting when you check its state? How would it ever be notified? – Andy Turner Jul 04 '16 at 09:06
  • 2
    Reinventing the wheel **is** bad practice, yes. Also: Your implementation does not handle an Exception that is thrown in `doSth()` ... – Fildor Jul 04 '16 at 09:10
  • @Andy Turner well it doesn't need to be notified when it's not waiting since it will be in the loop – NamHo Lee Jul 04 '16 at 09:25

2 Answers2

2

The benefit is: you are not re-inventing the wheel.

Seriously: maybe your simple worker thread does the job today. But chances are, that sooner or later; things will become more complex. In that sense, "programming" is always about balancing between "being open for change" versus "you ain't gonna need it".

The nice thing about the Executors framework is that it offers a clean, easy-to-grasp abstraction layer. Why worry about threads, when the only thing you care about is submitting tasks?

And you know: such abstractions allow for many things ... for example to write unit tests without worrying about things happening in different threads; by using a an executor that actually uses on the current thread. And everybody who has ever written unit tests for "multi threaded" code knows how hard that can be ..

Community
  • 1
  • 1
GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • well I do wish to achieve one thing through re inventing the wheel. I wish the thread maintains a some state information and I heard that newSingleThreadExecutor could just randomly destroy and recreate the thread. I'm just figuring out several ways to solve this problem – NamHo Lee Jul 04 '16 at 09:23
  • Well, then you should have mentioned that requirement in your question. Yes, you are correct, that service might create new threads, if required. But the point is: it will only do so if the underlying thread gets "sick". Do you intend to write all that code to detect "thread is sick" and "action required because of that" on your own? – GhostCat Jul 04 '16 at 09:28
  • If you need to share state between the tasks, do that: have a class to hold the shared state, and pass the same instance to each of your tasks when you create them. This doesn't require the use of "raw" threads. – Andy Turner Jul 04 '16 at 09:52
1

newSingleThreadExecutor is rather useful as special type of ExecutorService when the code expects it. It has just slight advantage over dedicated Thread. The only difference is that you don't have to reinvent the wheel with implementing your own queue, synchronization and things like that. It's optimized to use low level synchronization patterns to achieve best performance so I'd still recommend to use something existing if you expect similar functionality which is the case here.

Additionally, the code you provided is quite incorrect:

  1. No instantiation of the worker
  2. Missing synchronization around both wait() and notify().
  3. wait() and notify() are completely unnecessary here as the BlockingQueue implementations already provide waiting functionality.
Zbynek Vyskovsky - kvr000
  • 18,186
  • 3
  • 35
  • 43
  • yeah i did omit a few parts I should fix that,.. and the second is part of my last question but the third part you pointed out.. I'm kinda curious, wouldn't it make the worker thread unnecessarily busy if the loop goes on and on even when the queue is empty'? – NamHo Lee Jul 04 '16 at 09:21