Страницы

Поиск по вопросам

четверг, 15 ноября 2018 г.

Пример по многопоточности

Поясните, пожалуйста, где я могу быть не прав.
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

Комментариев нет:

Отправить комментарий