Страницы

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

воскресенье, 22 декабря 2019 г.

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

#java #многопоточность


Поясните, пожалуйста, где я могу быть не прав. 

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();
        }
    }
}

    


Ответы

Ответ 1



Только метод 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

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

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