Нужна помощь в задаче:
Нужно, чтобы поток Write
увеличивал значение числа на 1 и после каждого увеличения блокировался, а поток Reader
выводил данное значение и блокировался, поток Control
каждую секунду вызывал notifyAll()
, и работа программы продолжалась до десяти.
Проблема такова, что почему-то поток Reader
выводит числа по 2 раза (1,1,3,3 и т.д.).
И ещё подскажите, как в notifyAll()
поставить таймер, чтобы он вызывался каждую секунду.
Main:
public static void main(String[] args) {
Resource resource = new Resource();
Write write = new Write(resource);
Reader reader = new Reader(resource);
write.start();
reader.start();
while (!resource.end) {
new Thread(() -> {
synchronized (resource) {
resource.notifyAll();
}
}).start();
}
}
Write:
public class Write extends Thread {
Resource rs;
public Write(Resource rs) {
this.rs = rs;
}
@Override
public void run() {
synchronized (rs) {
//System.out.println("Write start");
while (!rs.end) {
rs.num++;
System.out.println("Write: " + rs.num);
try {
rs.wait();
} catch (InterruptedException ex) {
System.out.println(ex);
}
if (rs.num >= 10) {
rs.end = true;
}
}
}
}
}
Reader:
public class Reader extends Thread {
Resource rs;
public Reader(Resource rs) {
this.rs = rs;
}
@Override
public void run() {
synchronized (rs) {
System.out.println("Reader Start");
while (!rs.end) {
System.out.println("Reader : " + rs.num);
try {
rs.wait();
} catch (InterruptedException ex) {
System.out.println(ex);
}
}
}
}
}
Resourse:
public class Resource {
int num;
boolean end;
}
Основная проблема в приведённом вами варианте решения задачи - полное отсутствие синхронизации между потоками. Отсюда и следствие - reader может несколько раз прочитать одно и то же значение, writer - записать без ожидания чтения. Обычно алгоритм синхронизации между потоками выглядит следующим образом: поток выполняет цикл пока не будет прерван либо не выполнится некое условие (в вашем случае rs.end), внутри цикла происходит блокировка общего ресурса и сразу осуществляется проверка, разрешает ли логика приложения воспользоваться потоку этим ресурсом. Для этого, например, можно ввести boolean переменные, которые определяют, какому потоков на данный момент разрешено использовать ресурс. Примерно так я вижу решение вашей задачи:
class Resource {
int num;
boolean end, isRead, isWrite, isControl;
}
Reader
@Override
public void run() {
while (!rs.end) {
synchronized (rs) {
while (!rs.isRead) {
try {
rs.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Reader : " + rs.num);
rs.isControl = true;
rs.isRead = false;
rs.notifyAll();
}
}
}
Writer
@Override
public void run() {
while (!rs.end) {
synchronized (rs) {
while (!rs.isWrite) {
try {
rs.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
rs.num++;
System.out.println("Write: " + rs.num);
if (rs.num >= 10) {
rs.end = true;
}
rs.isWrite = false;
rs.isRead = true;
rs.notifyAll();
}
}
}
Control
resource.isControl = true;
new Thread(() -> {
while (!resource.end) {
synchronized (resource) {
while (!resource.isControl) {
try {
resource.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
resource.isControl = false;
resource.isWrite = true;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
resource.isControl = false;
resource.isWrite = true;
resource.notifyAll();
}
}
}).start();
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Есть поле ввода (input), в котором через JavaScript автоматом прописывается начальное значение из трех символовС помощью такого скрипта я запрещаю...
Есть вот такой объект, из которого берет данные vue для отрисовкиПонадобилось хранить строковые представления кусочков кода (условий) в нем
Мне нужно в ангуляр выводить дату которую я записал в БД как параметрЯ вывожу но в таком виде: