public class Solution {
public static void main(String[] args) throws InterruptedException {
new NoteThread().start();
new NoteThread().start();
}
public static class Note {
public static final List<String> notes = new ArrayList<>();
public static void addNote(String note) {
notes.add(0, note);
System.out.println("Нить [" + Thread.currentThread().getName() + "] добавила заметку [" + note + "]");
}
public static void removeNote(String threadName) {
String note = notes.remove(0);
if (note == null) {
System.out.println("Другая нить удалила нашу заметку");
} else if (!note.startsWith(threadName)) {
System.out.println("Нить [" + threadName + "] удалила чужую заметку [" + note + "]");
} else {
System.out.println("Нить [" + threadName + "] удалила свою заметку [" + note + "]");
}
}
}
public static class NoteThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
Note.addNote(getName() + "-Note" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Note.removeNote(getName());
}
}
}
}
Немного модифицировал программу, чтобы понять что происходит.
Вывод получился такой:
Нить [Thread-0] добавила заметку [Thread-0-Note0]
Нить [Thread-1] добавила заметку [Thread-1-Note0]
Нить [Thread-1] удалила свою заметку [Thread-1-Note0]
Нить [Thread-0] удалила свою заметку [Thread-0-Note0]
Нить [Thread-1] добавила заметку [Thread-1-Note1]
Нить [Thread-0] добавила заметку [Thread-0-Note1]
Нить [Thread-0] удалила свою заметку [Thread-0-Note1]
Нить [Thread-1] удалила чужую заметку [Thread-0-Note1]
Нить [Thread-0] добавила заметку [Thread-0-Note2]
Нить [Thread-1] добавила заметку [Thread-1-Note2]
Нить [Thread-1] удалила свою заметку [Thread-1-Note2]
Нить [Thread-0] удалила чужую заметку [Thread-1-Note2]
Нить [Thread-1] добавила заметку [Thread-1-Note3]
Нить [Thread-0] добавила заметку [Thread-0-Note3]
Нить [Thread-1] удалила чужую заметку [Thread-0-Note3]
Нить [Thread-0] удалила свою заметку [Thread-0-Note3]
Нить [Thread-1] добавила заметку [Thread-1-Note4]
Нить [Thread-0] добавила заметку [Thread-0-Note4]
Нить [Thread-1] удалила чужую заметку [Thread-0-Note4]
Нить [Thread-0] удалила свою заметку [Thread-0-Note4]
Вопрос по выделенным сообщениям. Заметки выделенные жирным курсивом были удалены на предыдущем шаге (выделены просто жирным). Как такое происходит? И где удаление следующих заметок: Thread-0-Note2, Thread-1-Note3, Thread-1-Note4 ???fleek
25 уровень
Не понимаю принцип работы программы. Помогите, пожалуйста.
Решен
Комментарии (8)
- популярные
- новые
- старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Сергеев ВикторMaster
20 ноября 2018, 18:54
Тут у вас целая корзинка проблем ))
1. лист статичен, а значит он один для всех, т.е. это разделяемый между потоками ресурс, чтобы понять как с этим работать читайте про синхронизацию
2. "Заметки выделенные жирным курсивом были удалены на предыдущем шаге (выделены просто жирным). Как такое происходит?"
- предположил первая нить заходит в removeNote и вызывает notes.remove(0), никто не гарантирует атомарность данной операции, поэтому ничто не мешает потоку уснуть в процессе. Далее второй поток заходит в метод removeNote и вызывает notes.remove(0). Оба получают один и тот же объект и пишут лог о его удалении.
3. И где удаление следующих заметок: Thread-0-Note2, Thread-1-Note3, Thread-1-Note4 ???
Вы сами ограничили цикл 5 итерациями, оставшиеся запись остались в листе.
0
fleek
20 ноября 2018, 19:28
нет, я проверял, размер листа 0. в этом коде я просто не писал это.
Допишите после 4 строки в методе main:
Thread.sleep(7000); //нужно для того, чтобы addNote() и removeNote() завершились
System.out.println(notes.size());
На выходе будет 0.
0
Сергеев ВикторMaster
20 ноября 2018, 19:33
посмотрите в код метода ArrayList.remove можете его сюда выложить и тогда я тоже посмотрю )
0
fleek
20 ноября 2018, 19:39
0
Сергеев ВикторMaster
20 ноября 2018, 19:42
что будет если поток уснет на 6 строчке и в метод зайдет другой поток?
0
fleek
24 ноября 2018, 19:41
не знаю... не могу понять...
0
Сергеев ВикторMaster
24 ноября 2018, 21:43решение
может получиться так, что несколько потоков получат элемент, до того как он будет удален. Тогда они так же попробуют его удалить - вот ваши дублирующиеся записи, а поскольку объект уже удален, то они удалят следующий, запись о котором в лог не попадает.
+4
fleek
2 декабря 2018, 12:46
спасибо, разобрался
0