简体   繁体   中英

How to start a thread only if it is not executing or not started before, or only one instance of thread should be created

I have the following method, that called every time I click over a button, this results to start a new thread again and again when the button is pressed, that results to multiple initialisation of thread, however I want only one thread should get executed, how can I achieve this.

    private void scheduleMessages() {
    new Thread(new Runnable() {
        @Override
        public void run() {
         //Some operations
        }
    }).start();
}

Note: this is a small method and I don't want to create a separate class, just to make it singleton, so a solution without singleton pattern will be appreciated.

if you cannot make instance of this to check isActive() you should make a semaphore variable - a boolean, that you set to true when you start thread and set to false when you are done.

private void scheduleMessages() {
    if (!taskRunning){
        new Thread(new Runnable() {
            @Override
            public void run() {
               taskRunning = true;
               //Some operations
               taskRunning = false;
            }
        }).start();
    }
}

Have that thread be a background thread - maybe initialize it when the button is pressed the first time.

Have that thread listen to a queue - and act upon messages in that queue.

Whenever the button is pressed again, put a new message into the queue.

If your need to execute every requests but on a specific number of threads, you can use a thread pool and let the executor manage the queue .

private ExecutorService services;
private final static int POOL_SIZE = 1;

public MessagesService(){
    services = Executors.newFixedThreadPool(POOL_SIZE);
}

public void scheduleMessages(Runnable r){
    services.submit(r);
}

If you call addCall x times, x thread will be executed at the end but will never use more than the number of thread available in the pool. Here, 1 thread.


For a system that only accept one request, you can use the same approch but check the Future returned by a single thread executor. That way, you can check the status of the service.

private ExecutorService services;
private Future<?> lastCall; 

public MessagesService() {
    services = Executors.newSingleThreadExecutor();
    lastCall = null;
}

public synchronized void scheduleMessages(Runnable r) {
    if(!isScheduled()){
        lastCall = services.submit(r);
    }
}

public boolean isScheduled(){
    return lastCall != null && !lastCall.isDone();
}

That way, the Runnable doesn't need to update a flag, which give a reusable solution.

Here is a sample of the Runnable to test these codes :

new Runnable() { 
    System.out.println("Running");
    try {
       Thread.sleep(500);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM