Форум программистов, компьютерный форум, киберфорум
Java SE (J2SE)
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.56/18: Рейтинг темы: голосов - 18, средняя оценка - 4.56
746 / 493 / 285
Регистрация: 10.09.2015
Сообщений: 1,530
1

Остановка потоков

03.12.2017, 05:08. Показов 3214. Ответов 9
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Вот такой вопрос:

Допустим есть 1 класс, наследуемый от Runable:
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
//поток слежения за временем
class Time implements Runnable {
    private long ms;
    private String name;
 
    Time(String name, long ms) {
        this.name = name;
        this.ms = ms;
    }
 
    @Override
    public void run() {
        long ms = System.currentTimeMillis();
        try {
            //тут цикл ожидания времени, и если
            //второй поток закончил работу раньше, чем время ожидания
            //то просто закончить поток
            //если время ожидания исчерпано, закончить этот поток и другой
            System.out.printf("The thread [%s] is end work!%s", this.name, System.lineSeparator());
        } catch (InterruptedException e) {
            System.out.printf("The thread [%s] is stop!%s", this.name, System.lineSeparator());
        }
    }
}
есть второй поток:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class CountChar implements Runnable {
    private String name;
    private String offer;
 
    CountChar(String name, String offer) {
        this.name = name;
        this.offer = offer;
    }
 
    @Override
    public void run() {
        if (this.offer != null) {
            int countSymbols = 0;
            try {
                //тут мы считаем допустим кол-во символов в тексте
                System.out.printf("Text have %d symbols.%s", countSymbols, System.lineSeparator());
                System.out.printf("The thread [%s] is end work!%s", this.name, System.lineSeparator());
            } catch (InterruptedException e) {
                System.out.printf("The thread [%s] is stop!%s", this.name, System.lineSeparator());
            }
        }
    }
}
в другом классе есть 2 метода, :
1. Стартует и смотрит за потоками
2. завершает потоки
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
public void start() {
        Thread time = new Thread(new Time("ThreadTime", ms));
        Thread countChar = new Thread(new CountChar("ThreadCountChar", this.offer));
        time.start();
        countChar.start();
        while (!time.isInterrupted() || !countChar.isInterrupted()) {
            if (time.isInterrupted() && !countChar.isInterrupted()) {
                stopThread(countChar);
            }
            if (countChar.isInterrupted() && !time.isInterrupted()) {
                stopThread(time);
            }
        }
    }
 
    private void stopThread(Thread thread) {
        if (thread != null) {
            if (!thread.isInterrupted()) {
                thread.interrupt();
                try {
                    thread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
В общем не буду говорить, что код ай удачный и прям классный. Нет. С потоками я не так дружу.
Вот в чём вопрос:
Если бы я делал класс наследуемый от Thread, то завершить поток нет проблем
В методе run() проверял бы методом isInterputed и если что, кидал бы эксепшн или выходил из цикла
Но тут как проверить флаг о завершении потока и завершить, если он true?
Thread.sleep(ms), который кидает как раз ексепшн и завершает поток методом iterputed(), мне использовать нельзя.
Как обойтись без него и методов бубнов с доп. переменными и методами? Кто нибудь имеет опыт?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
03.12.2017, 05:08
Ответы с готовыми решениями:

Остановка потоков после 3 секунд работы
Народ, помогите плиз разобраться как работать с потоками. Такое вот задание: Напишите класс,...

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

Остановка потока
Делаю игру на java eclipse. Использую потоки. С помощью них создаю изображения на фрейме,...

Остановка выполнения
Написал программу, которая постоянно шлёт информацию по сокету на сервер и получает какой-то ответ....

9
Автоматизируй это!
Эксперт Python
7193 / 4684 / 1222
Регистрация: 30.03.2015
Сообщений: 13,364
Записей в блоге: 29
03.12.2017, 17:16 2
ArtemFM, без обид, но нагородил ты тут. Хотя всегда есть вариант, что я не все понял, да и код не весь.
1) в раннабл в методе ран никто не мешает тебе вызвать
Java
1
 Thread.currentThread().isInterrupted();
2) не понял зачем следить за потоками? у тебя там вечные циклы? как только выполнится код из метода ран они сами завершатся, можно просто в главном классе заджойниться к ним и подождать
Java
1
2
time.join();
countChar.join();
3) работать с интерраптед не совсем айс, почитай про особенности (там например может isInterrupted вернуть false если на момент интеррапт поток уже завершен), можно проверять свойство isAlive() потока к примеру, но зависит от задач.
0
746 / 493 / 285
Регистрация: 10.09.2015
Сообщений: 1,530
03.12.2017, 18:55  [ТС] 3
Такова задача...
создать 2 потока... Один выполняет работу, другой следит за временем

Допустим дана 1 сек. То, который смотрит за временем, смотрит, если 2-й поток закончил работу, то и этот заканчивает. Если не закончил через сек, то сами заканчиваем тот. Грубо говоря так...

Там нет бесконечного потока. Просто задача на принудительное завершение потока, если он превзошёл лимит времени

time.join();
countChar.join();

будут ждать до конца работы обоих потоков, что не по задаче

Thread.currentThread().isInterrupted(); - пробовал первым. Что-то он не всегда отрабатывает. Хотя может я затупил...

Вот сама задача:
1. В программе необходимо реализовать механизм остановки нити.
2. В программе должно быть две нити. Одна нить проверять общее время работы программы.
Если время работы программы больше заданного времени, необходимо остановить выполнение программы.
3. Вторая нить - это программа для подсчета символов в тексте.

Помните, что метод Thread.interrupt() - выставлять флаг, но не останавливает нить.

public class Time impl Runnable

public class CountChar impl Runnable

Добавлено через 1 минуту
Это я обучаю сейчас потоки просто, поэтому такова задача для понимания. Но уж очень не хочется использовать Thread.sleep(), он же замедлит скорость цикла, что меня не радует

Добавлено через 1 час 20 минут
Второй раз за месяц задал вопросы про потоки )
Ответил 1 человек...

Неужто никто не имеет опыта с потоками? Жалььь
0
Эксперт функциональных языков программированияЭксперт Java
4539 / 2732 / 486
Регистрация: 28.04.2012
Сообщений: 8,628
03.12.2017, 21:23 4
Цитата Сообщение от ArtemFM Посмотреть сообщение
Неужто никто не имеет опыта с потоками?
Наверняка, много кто имеет, но обычно решают реальные задачи практическими методами, а не синтетику.

Цитата Сообщение от ArtemFM Посмотреть сообщение
Но уж очень не хочется использовать Thread.sleep(), он же замедлит скорость цикла
Что ты имеешь в виду?
0
746 / 493 / 285
Регистрация: 10.09.2015
Сообщений: 1,530
03.12.2017, 21:32  [ТС] 5
Допустим:
Java
1
2
3
for (int i = 0; i < 10; i++) {
   count++;
}
допустим каждый шаг в цикле происходит за n наносекунд
следовательно полное время будет n * 10
то:
Java
1
2
3
4
for (int i = 0; i < 10; i++) {
   Thread.sleep(ms);
   count++;
}
то этот цикл затратит времени
(n*10) + (ms*10)
больше, чем просто цикл без задержки
Так ведь?
0
Эксперт функциональных языков программированияЭксперт Java
4539 / 2732 / 486
Регистрация: 28.04.2012
Сообщений: 8,628
03.12.2017, 22:42 6
Зачем тебе Thread.sleep в цикле подсчёта количества символов?

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import java.math.BigInteger;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
 
public final class CountTimed {
 
    public static void main(String[] args) throws Exception {
        final ExecutorService executorService = Executors.newFixedThreadPool(2);
        final AtomicBoolean aborted = new AtomicBoolean(false);
        try {
            final Future<BigInteger> count = executorService.submit(() -> countCharsWithLimit(aborted::get));
            final Future<Boolean> done = executorService.submit(() ->
                await(count, 1, TimeUnit.SECONDS,
                        (result) -> System.out.println("count = " + result),
                        () -> {
                            aborted.set(true);
                            System.out.println("timeout");
                        }
            ));
            System.out.println("waiting for result...");
            //aborted.set(true); // uncomment to emulate successful (before timeout) end of countCharsWithLimit
            done.get();
        } finally {
            executorService.shutdown();
        }
    }
 
    private static <T> boolean await(
            Future<T> future,
            long timeout,
            TimeUnit unit,
            Consumer<T> resultConsumer,
            Runnable timeoutAction
    ) throws ExecutionException, InterruptedException {
        try {
            final T result = future.get(timeout, unit);
            resultConsumer.accept(result);
            return true;
        } catch (TimeoutException e) {
            future.cancel(true);
            timeoutAction.run();
            return false;
        }
    }
 
    private static BigInteger countCharsWithLimit(BooleanSupplier aborted) {
        BigInteger count = BigInteger.ZERO;
        while (!aborted.getAsBoolean()) {
            count = count.add(BigInteger.ONE);
        }
        return count;
    }
}
0
Автоматизируй это!
Эксперт Python
7193 / 4684 / 1222
Регистрация: 30.03.2015
Сообщений: 13,364
Записей в блоге: 29
04.12.2017, 20:11 7
Лучший ответ Сообщение было отмечено ArtemFM как решение

Решение

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

ArtemFM, теперь, когда есть задача, можно еще что-то обсудить...
пока писал тебе как можно делать, понял что непонятно получается, вот набросал кода.
Мейн
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Main {
    public static void main(String[] args) {
        CountChar countChar = new CountChar("String"); // я не знаю какие тексты ты там передаешь, просто пример
        Thread countThread = new Thread(countChar);
        Thread timeThread= new Thread(new Time(countThread,countChar,600)); //600 миллисекунд ждет поток времени
        timeThread.start();
        countThread.start();
        try {
            timeThread.join(); //джойнимся чтобы дождаться завершения потока времени
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
 
}
класс работяга
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
public final class CountChar implements Runnable {
    private volatile boolean flag =true; //флаг что еще можно работать и никто не требует остановки
    private final String textToWork; //это твой текст который ты передаешь, что с ним дальше делать решай
 
    public void setFlag(boolean flag) { /метод для внешних объектов для требования остановки
        this.flag = flag;
    }
 
    public CountChar(String textToWork) {
        this.textToWork = textToWork;
    }
 
    @Override
    public void run() {
        int count=0; //не надо так делать, я тут просто имитирую некоторую работу
        while (flag) { //пока не просят остановки            
            try {
                Thread.sleep(500); //вместо этого что то делаем с текстом
                System.out.println(".");
                count++;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
           if(count>=4){ //тут мы все сделали и просто завершаемся
                break;
           }
        }
    }
}
класс тайм
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
public final class Time implements  Runnable {
    private final Thread countCheckThread;
    private final CountChar countChar;
    private final long timeInMilliseconds; //время ожидания в миллисекундах
 
    public Time(Thread countCheckThread, CountChar countChar, long timeInMilliseconds) {
        this.countCheckThread = countCheckThread;
        this.countChar = countChar;
        this.timeInMilliseconds = timeInMilliseconds;
    }
 
    @Override
    public void run() {
        long startTime =System.currentTimeMillis(); //начало отсчета
        while (countCheckThread.isAlive()){ //пока работяга еще жив и пашет
            long nowTime = System.currentTimeMillis();
            if (nowTime-startTime>=timeInMilliseconds) { //время истекло
                countChar.setFlag(false); //просим работягу остановиться
                System.out.println("Time is over! Stopping thread ...");
                try {
                    countCheckThread.join(); //ждем чтобы работяга остановился (там быстро)
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println("Time elapsed: " + (System.currentTimeMillis()-startTime)); //время выводим в любом случае
    }
}
0
746 / 493 / 285
Регистрация: 10.09.2015
Сообщений: 1,530
04.12.2017, 20:28  [ТС] 8
Welemir1, спасибо. Вы абсолютно правы, что нужно 2 класса типа Runnable.
Одна нить будет считать кол-во символов в тексте
Вторая нить ждать определённого времени и если оно исчерпано, то завершаются 2 нити
Если нить-работяга закончила раньше заданного времени ожидания, то так же 2 нити заканчивают свою работу (нет смысла тогда ждать заданного времени)

Это тестовая задача, а быть может будут существовать 2 потока....
Один работает долго... Около часа и нам к примеру нужно, чтоб вот кровь из носа, чтоб если за час первая нить не закончила свою работу, завершить её насильно. Но если вдруг к примеру нить-работяга справилась за 20 мин, грубо говоря, то нет смысла ждать час и потом проверять. Сразу 2 нити заканчивают свою работу.

Добавлено через 3 минуты
Ваш код мне понятен, используете флаг boolean. Была такая мысль. Думаю, так и сделаю. Спасибо за код. Потраченное время человека - дорогого стоит!
0
Автоматизируй это!
Эксперт Python
7193 / 4684 / 1222
Регистрация: 30.03.2015
Сообщений: 13,364
Записей в блоге: 29
04.12.2017, 20:45 9
Лучший ответ Сообщение было отмечено ArtemFM как решение

Решение

ArtemFM, у меня собственно если время истекает, то все потоки завершаются, как вам и хотелось.
Почитайте еще wait, notify, с ними то еще проще пожалуй будет:
- если поток задачу доделал то просто делает натифай второму чтоб не считал больше время
- если вейт (а он есть и по времени) не отработал то интерраптим
0
746 / 493 / 285
Регистрация: 10.09.2015
Сообщений: 1,530
05.12.2017, 02:34  [ТС] 10
Спасибо, я про это знаю, но пока сея новшество нельзя использовать. Всё по порядку тут на курсе... Так бы не было вопросов ))) Спасибо ещё раз
0
05.12.2017, 02:34
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
05.12.2017, 02:34
Помогаю со студенческими работами здесь

Остановка потока
public class Potok implements Runnable { @Override public void run() { while...

Остановка мелодии
Подскажите пожалуйста как можно сделать что бы при нажатии на кнопку мелодия останавливалась. В...

Остановка forEach
try { Stream&lt;String&gt; stringStream = Files.lines(path, StandardCharsets.UTF_8); ...

остановка потока
Начал изучать нити. Возник вопрос. Открываю новый потом main, жду 5 секунд и методом - iinterrup...


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

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru