Поясните, пожалуйста, где я могу быть не прав.
1. Главный поток main запускает два потока: t1, t2.
2. Поток main останавливается и ждет завершения потоков t1 и t2 так как вызваны методы t1.join и t2.join
3. Первый поток t1 несколько раз засыпает при выполнении, но второй не может начать выполнения метода writing, так как он synchronized. В результате после работы первого потока в файле имеем запись:
First0->0 First1->1 First2->2 First3->3 First4->4
4. После окончания первого потока, второй делает тоже самое.
5. Два потока завершены, поток main завершает выполнение.
В результате в файле мы можем иметь только запись вида:
First0->0 First1->1 First2->2 First3->3 First4->4 Second0->0 Second1->1 Second2->2 Second3->3 Second4->4
Но в учебнике приводиться другой результат. Как такое возможно?
import java.io.FileWriter;
import java.io.IOException;
/**
* Created by IP44 on 25.11.2016.
*/
class Synchro {
private FileWriter fileWriter;
public Synchro(String file) throws IOException {
fileWriter = new FileWriter(file, true);
}
public void close() {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public synchronized void writing(String str, int i) {
try {
System.out.print(str + i);
fileWriter.append(str + i);
Thread.sleep((long)(Math.random() * 50));
System.out.print("->" + i + " ");
fileWriter.append("->" + i + " ");
} catch (Exception e) {
System.err.print("Error of stream");
e.printStackTrace();
}
}
}
class MyThread extends Thread {
private Synchro s;
public MyThread(String str, Synchro s) {
super(str);
this.s = s;
}
public void run() {
for (int i = 0; i < 5; i++) {
s.writing(getName(), i);
}
}
}
public class SynchroThreads {
public static void main(String[] args) {
try {
Synchro s = new Synchro("C:\\Users\\IP44\\Downloads\\data.txt");
MyThread t1 = new MyThread("First", s);
MyThread t2 = new MyThread("Second", s);
t1.start();
t2.start();
t1.join();
t2.join();
s.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Ответ
Только метод write помечен как synchronized, но не метод run, в котором находится цикл. Так что порядок выводв может быть любой. Это можно явно увидеть, если добавить немного ожидания в сам run - если бы порядок был задан блокировками, он бы не поменялся.
http://ideone.com/joXG0N
public void run() {
try {
for (int i = 0; i < 5; i++) {
s.writing(getName(), i);
Thread.sleep((long)(Math.random() * 50));
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
First0->0
Second0->0
First1->1
Second1->1
First2->2
Second2->2
First3->3
Second3->3
First4->4
Second4->4
Но в учебнике приводиться другой результат.
Там не об этом. Там о том, что
System.out.print(str + i);
fileWriter.append(str + i);
Thread.sleep((long)(Math.random() * 50)); // <-- В этом месте
System.out.print("->" + i + " ");
fileWriter.append("->" + i + " ");
даже несмотря на sleep переключения на другой write не будет. Т. е. мы никогда не увидим такого:
First->Second->0->0
Комментариев нет:
Отправить комментарий