Форум программистов, компьютерный форум, киберфорум
Java
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/9: Рейтинг темы: голосов - 9, средняя оценка - 4.67
0 / 0 / 0
Регистрация: 21.08.2017
Сообщений: 9

Как избежать мультизапуска потока?

06.09.2017, 12:33. Показов 1970. Ответов 12
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет, я начинающий в JAVA и возможно мой вопрос покажется простым, но не судите строго.

Для примера, делаю кнопку и кидаю в обработчик нажатия такое:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//онКлик
new Thread(new MyRunnable()).start();
 
 
//**
public class MyRunnable implements Runnable {
    private static int runCount = 0;
 
    @Override
    public void run() {
        runCount++;
 
        Log.e(TAG, "Now MyRunnable is running " + String.valueOf(runCount) + " times");
        try { Thread.sleep(2000); } catch(InterruptedException e) {  }
 
        runCount--;
 
    }
 
}
Тут мне как бы более менее понятно, каждый раз он будет запускать новый поток и все они параллельно будут работать.
А мне надо чтобы новый поток не запускался до тех пор пока не завершится предыдущий.

Делаю так:

Java
1
2
3
4
5
private Thread myThread;
 
//онКлик
myThread = new Thread(new MyRunnable());
myThread.start();
не помогает.

тогда делаю так:

Java
1
2
3
4
5
6
7
8
9
10
//онКлик
                if (myThread == null) {
                    myThread = new Thread(new MyRunnable());
                    myThread.start();
                }else {
                    if(!myThread.isAlive()) {
                        myThread = new Thread(new MyRunnable());
                        myThread.start();
                    }
                }
помогает! но как-то это очень криво мне кажется выглядит. наверняка есть какой-то более простой способ сделать так чтобы новый поток не запускался до того как не завершится предыдущий. Должно быть какое-то общепринятое решение.

В MyRunnable() у меня чтение с инета в буфер, а буфер опустошается по таймеру из другого потока и если там уже мало данных запускается MyRunnable() пополнить буфер, фишка в том, что если какой-то тормоз в сети новый вызов на поток может случится раньше, чем завершиться предыдущий. Вот этого мне и надо избежать, чтобы два потока сразу не пытались читать с инета.

В общем, надеюсь на совет.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
06.09.2017, 12:33
Ответы с готовыми решениями:

Как избежать блокировки потока?
Всем привет! В общем ситуация такая: есть задача: сжатие gzipstream в мультипоточной среде(да-да, эта тема тут ни раз обсуждалась). ...

Как избежать уничтожения потока после выполнения им своей функции?
создаю несколько потоков for (int i = 0; i < n; i++) BeeThreads = CreateThread(NULL, 0, &Bee_Thread, (CONST LPVOID)i, 0, NULL); ...

Как избежать блокировки основного UI потока при вызове Thread.Sleep в вспомогательном потоке?
Добрый день! Создаю событие для создаваемой кнопки следующим образом: btnStartTool.Click += (sender1, e1) => ...

12
20 / 23 / 24
Регистрация: 20.10.2016
Сообщений: 45
06.09.2017, 13:27
Думаю метод
Java
1
join()
класса Thread должен тебе помочь.

Добавлено через 11 минут
Хотя щас посмотрел внимательнее, у тебя тут вроде всего одна переменная для потока которую ты перезаписываешь, так что возможно и не подойдет.

Добавлено через 16 минут
Еще твое условие можно объединить в одно вот так:
Java
1
2
3
4
   if (myThread == null || !myThread.isAlive()) {
        myThread = new Thread(new MyRunnable());
        myThread.start();         
    }
1
 Аватар для rerf2010rerf
46 / 79 / 6
Регистрация: 10.08.2013
Сообщений: 237
06.09.2017, 13:42
Почитай про ExecutorService, в частности вам может помочь SingleThreadExecutor.
1
20 / 23 / 24
Регистрация: 20.10.2016
Сообщений: 45
06.09.2017, 13:48
Можно сделать через Executor с одним потоком:
Java
1
  private ExecutorService executor = Executors.newSingleThreadExecutor();
А в онклик добавлять новую задачу, тогда они встают в очередь:
Java
1
  executor.execute(new MyRunnable());
Добавлено через 1 минуту

Не по теме:

Не заметил ответ выше

1
0 / 0 / 0
Регистрация: 21.08.2017
Сообщений: 9
06.09.2017, 13:55  [ТС]
Цитата Сообщение от rerf2010rerf Посмотреть сообщение
Почитай про ExecutorService, в частности вам может помочь SingleThreadExecutor.
Цитата Сообщение от spid3y Посмотреть сообщение
Можно сделать через Executor с одним потоком:
Экзекутором попробовал сейчас, работает на половину. Он действительно не запускает несколько потоков параллельно, но он ставит их в очередь и если я тыкну по кнопке 5 раз - он последовательно запустит поток 5 раз, а мне надо чтобы он вообще не запускал его пока предыдущий поток не отработал.

Цитата Сообщение от spid3y Посмотреть сообщение
Еще твое условие можно объединить в одно вот так:
этот намного лучше, чем мой вариант.
0
2884 / 2296 / 769
Регистрация: 12.05.2014
Сообщений: 7,978
06.09.2017, 14:06
я бы тупо блокировал кнопку пока задача выполняется, а по завершении задача через callback делает кнопке что-то типа setEnable(true);
1
0 / 1 / 0
Регистрация: 09.09.2017
Сообщений: 4
10.09.2017, 08:22
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//онКлик
public class OnClick implements MyRunnableListener{
public OnClick(){
// первый запуск
    new Thread(new MyRunnable(this)).start();
}
    public void finishMyRunnable(){
           // запуск после окончания потока или 
           //устанавливай какую либо переменную 
           // от состояния которой запускается поток по нажатию кнопки
           new Thread(new MyRunnable(this)).start();
       }
}
 
public interface MyRunnableListener{
    public void finishMyRunnable();
} 
 
//**
public class MyRunnable implements Runnable {
    MyRunnableListener listener = null;
    private static int runCount = 0;
    public MyRunnable(MyRunnableListener listener){
         this.listener=listener;
    } 
    @Override
    public void run() {
        runCount++;
        Log.e(TAG, "Now MyRunnable is running " + String.valueOf(runCount) + " times");
        try { Thread.sleep(2000); } catch(InterruptedException e) {  }
 
        runCount--;
        // поток закончился
        listener.finishMyRunnable();
    }
 
}
1
0 / 0 / 0
Регистрация: 21.08.2017
Сообщений: 9
11.09.2017, 13:36  [ТС]
не очень понял логику, если честно.
0
0 / 1 / 0
Регистрация: 09.09.2017
Сообщений: 4
11.09.2017, 14:01
Попробую объяснить на очень простом языке, практически на пальцах.
1. Допустим у нас есть интерфейс MyRunnableListener, в котором есть метод finishMyRunnable().
2. В конструктор класса MyRunnable заходит интерфейс MyRunnableListener как параметр.
3. в методе run этого класса, в конце вызывается метод finishMyRunnable интерфейса MyRunnableListener. Этот метод говорит что исполнение потока закончилось.

Осталось за малым, реализовать интерфейс MyRunnableListener в любом классе. Для примера я написал класс OnClick.

Логика такая:

1. в конструкторе OnClick запускается поток MyRunnable
Java
1
2
3
4
public OnClick(){
// первый запуск
    new Thread(new MyRunnable(this)).start();
}
this - это объект класса OnClick , который реализовал интерфейс MyRunnableListener

2. По завершению MyRunnable.run() вызывается метод finishMyRunnable интерфейса MyRunnableListener(в данном случае класс OnClick, метод finishMyRunnable ).

3. Смотрим реализацию MyRunnableListener класса OnClick. В методе finishMyRunnable делаем обработчик. Тут зависит от фантазии
- запускаем повторно MyRunnable,
- присваиваем значение события какой либо переменной и используем ее в другом коде. Например boolean isFinishThread = true;
- как советовали выше делаем кнопку setEnable(true);
0
2884 / 2296 / 769
Регистрация: 12.05.2014
Сообщений: 7,978
11.09.2017, 14:20
rcoma, потому что там этой логики практически нет
лучше не засоряй себе мозги, не вчитывайся в тот код выше - там бреда больше чем здравого смысла

Цитата Сообщение от syzonix Посмотреть сообщение
конструкторе OnClick запускается поток MyRunnable
все, дальше можно не читать
0
0 / 0 / 0
Регистрация: 21.08.2017
Сообщений: 9
11.09.2017, 14:28  [ТС]
Цитата Сообщение от syzonix Посмотреть сообщение
Попробую объяснить на очень простом языке,
Ну вообще пример полезный, я как-то думал, что логически должна быть возможность блокировать мультизапуск из Runnable, те если сама логика Runnable не подразумевает мультизапуск, но ведь тогда это можно сделать на уровне класса - просто воткнув счетчик и не делая полезную работу пока счетчик не обнулится отработавшим объектом, т.е. быстро завершать Runnable в обход его полезного кода?

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

В Runnable читаются данные с инета причем в цикле (небольшими порциями). Причем мы можем запустить несколько потоков читая с разных сайтов, но нам нежелательно запускать чтение с одного и того же сайта пока не отработал предыдущий поток чтения с этого сайта.
0
0 / 1 / 0
Регистрация: 09.09.2017
Сообщений: 4
11.09.2017, 15:07
Я напишу только принцип.
допустим есть где-то List<String>, который хранит URL сайтов(можно так List<URL>, зависит от нужды) с которых идет скачивание данных.
Измените интерфейс на
Java
1
2
3
public interface MyRunnableListener{
    public void finishMyRunnable(String url);
}
засовываете в MyRunnable этот интерфейс.
Подправляете логику в классе который запускает MyRunnable и работает с List<String>. Типа если есть url в List<String> то не запускаете MyRunnable с этим Url, а если нет то запускаете. Если MyRunnable запускается то добавляете url в List<String>
Как поток закончится, вызываете finishMyRunnable(url), в этом методе реализуете удаление url из List<String> и далее зависит от фантазии и вашей логики. Да, так как у вас многопоточное приложение то List<String> должен быть потокозащищенным, например CopyOnWriteArrayList или используйте synchronized.
0
43 / 3 / 3
Регистрация: 02.09.2017
Сообщений: 217
12.09.2017, 20:22
Я сам начинающий, но в конструкторах - редакторах игр это делалось просто. Берутся 2 boolean переменные. Например, a и b. Далее переменная a привязывается к кпонке. Переменная b к процессу. Первоначальные значения a = true; b=false. Нажатие на кнопку - a=false, запускается поток и b = true. Пока a = false - нажатие на кнопку невозможно. Поток закончился - b=false, a=true. Кнопка доступна для нажатия.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
12.09.2017, 20:22
Помогаю со студенческими работами здесь

Обработать процедуру из другого потока и избежать ошибки "элемент управления создан в другом потоке"
Добрый вечер, собственно есть проблема с реализацией второго потока, пишет что элемент управления создан в другом потоке, перечитал кучу...

Как из потока управлять формой, если функции потока находятся в другом классе?
Добрый вечер. Возник такой вопрос, никак не могу разобраться. Как из потока управлять формой, если функции потока находятся в другом...

Как из одного потока узнать состояние другого потока
Подскажите пожалуйста, как из одного потока узнать, что другой поток еще не запущен. Например, второй поток формируется в классе...

VC++6.0, как из порожденного потока прочитать переменную главного потока?
Visual C++ 6.0 SP5 Простое диалоговое окно, (MFC) созданное мастером среды VC По нажатию на кнопку создаю поражденный поток, в...

Утечка памяти в программе , как избежать или как правильно уничтожить объект?
Ребят помогите создал класс , вызываю его Creat после destroy ,проект работает только вот память используемая потихоньку растет через пять...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Новые блоги и статьи
1С: Программный отбор элементов справочника Номенклатура по группе
Maks 22.03.2026
Установка программного отбора элементов справочника "Номенклатура" из модуля формы документа. В качестве фильтра для отбора справочника служит группа номенклатуры. Отбор под наименованию группы (на. . .
Как я обхитрил таблицу Word
Alexander-7 21.03.2026
Когда мигает курсор у внешнего края таблицы, и нам надо перейти на новую строку, а при нажатии Enter создается новый ряд таблицы с ячейками, то мы вместо нервных нажатий Энтеров мы пишем любые буквы. . .
Krabik - рыболовный бот для WoW 3.3.5a
AmbA 21.03.2026
без регистрации и смс. Это не торговля, приложение не содержит рекламы. Выполняет свою непосредственную задачу - автоматизацию рыбалки в WoW - и ничего более. Однако если админы будут против -. . .
1С: Программный отбор элементов справочника Сотрудники по значению перечисления
Maks 21.03.2026
Установка программного отбора элементов справочника "Сотрудники" из модуля формы документа. В качестве фильтра для отбора служит предопределенное значение перечислений. Процедура. . .
Переходник USB-CAN-GPIO
Eddy_Em 20.03.2026
Достаточно давно на работе возникла необходимость в переходнике CAN-USB с гальваноразвязкой, оный и был разработан. Однако, все меня терзала совесть, что аж 48-ногий МК используется так тупо: просто. . .
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru