Как запустить поток, только если он не выполняется или не запускался раньше, или должен быть создан только один экземпляр потока - PullRequest
1 голос
/ 12 апреля 2019

У меня есть следующий метод, который вызывается каждый раз, когда я нажимаю на кнопку, это приводит к повторному запуску нового потока снова и снова при нажатии кнопки, что приводит к многократной инициализации потока, однако я хочу, чтобы только один поток должен быть казненным, как я могу достичь этого.

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

Примечание: это небольшой метод, и я не хочу создавать отдельный класс, просто сделать его одноэлементным, поэтому будет приветствоваться решение без одноэлементного шаблона.

Ответы [ 3 ]

1 голос
/ 12 апреля 2019

если вы не можете сделать экземпляр этого для проверки isActive(), вы должны сделать переменную семафора - логическое значение, которое вы устанавливаете в true, когда вы запускаете поток, и в false, когда вы закончите.

private void scheduleMessages() {
    if (!taskRunning){
        new Thread(new Runnable() {
            @Override
            public void run() {
               taskRunning = true;
               //Some operations
               taskRunning = false;
            }
        }).start();
    }
}
0 голосов
/ 12 апреля 2019

Если вам нужно выполнять все запросы, кроме определенного количества потоков, вы можете использовать пул потоков и позволить исполнителю управлять очередью.

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);
}

Если вы вызовете addCall x раз, x thread будет выполнен в конце, но никогда не будет использовать больше, чем количество потоков, доступных в пуле. Здесь 1 тема.


Для системы, которая принимает только один запрос, вы можете использовать тот же подход, но проверить Future, возвращенный одним исполнителем потока. Таким образом, вы можете проверить статус услуги.

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();
}

Таким образом, Runnable не нужно обновлять флаг, который дает повторно используемое решение.

Вот пример Runnable для проверки этих кодов:

new Runnable() { 
    System.out.println("Running");
    try {
       Thread.sleep(500);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
0 голосов
/ 12 апреля 2019

Пусть этот поток является фоновым потоком - возможно, инициализируйте его при первом нажатии кнопки.

Пусть этот поток прослушивает очередь - и обрабатывает сообщения в этой очереди.

При каждом повторном нажатии кнопки помещайте новое сообщение в очередь.

...