Изменить значение AtomicBoolean в runnable различными методами - PullRequest
1 голос
/ 30 октября 2019

MyRunnable имеет атомарный логический тип, который должен быть установлен в true одним методом, а другой метод - в false в многопоточной среде

   private final class MyRunnable<V> implements Runnable {

    private  AtomicBoolean atomicBoolean;

    public RunnableStudentFuture(AtomicBoolean atomicBoolean) {
        this.atomicBoolean = atomicBoolean;
    }

    @Override
    public void run() {

        while (!atomicBoolean.get()) {
            //spin
        }
    }
}

Когда я выполняю этот метод, цикл while в runnable будет вращатьсяпока атомное логическое значение не установлено равным true

public void setToFalse() {
        ExecutorService executorService =  Executors.newFixedThreadPool(4);
        AtomicBoolean atomicBoolean = new AtomicBoolean(false);
        executorService.submit(new RunnableStudentFuture(atomicBoolean));
    }

Ищем метод, подобный setToTrue, для выхода из цикла while. Что-то вроде сигнализации

public void setToTrue() {

    }

Как мне добиться этого в многопоточной среде?

Можно ли добиться этого с помощью CompletableFuture

1 Ответ

1 голос
/ 30 октября 2019

Важно помнить, что вам нужно (как-то) ссылаться на atomicBoolean из любого потока, для которого вы хотите установить его значение. Поскольку это закрытый член в Runnable, это означает, что вы должны:

  1. предоставить метод в этом runnable для установки значения;и
  2. сохраните ссылку на экземпляр этого работоспособного объекта.

В приведенном ниже примере я добавил методы в MyRunnable для включения установки значения.

public class MyRunnable implements Runnable {
    private final AtomicBoolean atomicBoolean = new AtomicBoolean();

    public void setToFalse() {
        this.atomicBoolean.set(false);
    }

    public void setToTrue() {
        this.atomicBoolean.set(true);
    }

    @Override
    public void run() {
        this.setToFalse();
        while (!atomicBoolean.get()) {
            System.out.println("running like mad");
            try {Thread.sleep(150L);} catch (Exception e) {}
        }
    }
}

Чтобы вызвать метод setToTrue, вам нужно иметь доступную ссылку на экземпляр в другом потоке. Для иллюстрации:

public static void main(String... none) throws Exception {
    MyRunnable myRunnable = new MyRunnable();

    System.out.println("starting runnable on different thread");
    ExecutorService executorService = Executors.newFixedThreadPool(4);
    executorService.execute(myRunnable);

    System.out.println("wait on main thread");
    try {Thread.sleep(1000L);} catch (Exception e) {}

    System.out.println("calling set to true on main thread");
    myRunnable.setToTrue(); 
}

этот метод выполнит runnable в другом потоке, а затем через некоторое время вызовет setToTrue в исходном потоке. Вы бы увидели вывод так:

starting runnable on different thread
wait on main thread
running like mad
running like mad
running like mad
running like mad
running like mad
running like mad
running like mad
calling set to true on main thread
...