/ / Dlaczego moje dane wejściowe pokazują, że jeden wątek działa po drugim, a nie w tym samym czasie? - Java, wielowątkowość

Dlaczego moje dane wejściowe pokazują, że jeden wątek działa po drugim, a nie w tym samym czasie? - Java, wielowątkowość

Badałem koncepcję wątku i zauważyłem, że kod ma być uruchamiany w dwóch procesach jednocześnie. Oto mój kod

public class Connor extends Thread{

public void run() {
for(int i=0; i< 10; i ++){
System.out.println("Hello " + i);
}

public static void main(String[] args){
Connor runner1 = new Connor();
Connor runner2 = new Connor();
runner1.start();
runner2.start();
}
}

I moje wyjście http://imgur.com/yAZqgal

Wygląda na to, że dwa wątki zaczynają się odw tym samym czasie (osobne procesy, jak wskazują dwa początkowe 0), ale jeden wykonuje (1-9), a drugi wykonuje (1-9). Po założeniu, że mają one również przeplatać się (1,1,2,2, ...) bc oba wątki drukują na konsoli. Zbadałem i zobaczyłem, że start jest właściwą metodą, ponieważ mówi klasie wątku, aby wykonać metodę uruchamiania w innym wątku? Czy ktoś może wyjaśnić, dlaczego otrzymuję ten wynik?

Odpowiedzi:

5 dla odpowiedzi № 1

Powiedz, że masz dziesięć spraw do załatwieniasiostra ma dziesięć spraw do załatwienia, a ona ma tylko jeden samochód. Czy po każdym zleceniu przywozisz samochód i zmieniasz kierowców? Oczywiście nie. To byłoby absurdalnie nieefektywne. Każdy wątek potrzebuje tylko strumienia wyjściowego. Absurdem byłoby ich ścisłe przeplatanie.


3 dla odpowiedzi № 2

Twój kod wygląda dobrze. Myślę, że twoje wątki nie działają równolegle tylko dlatego, że kończą się szybko. Zmień limit pętli z 10 na 1000, a zobaczysz efekt.

Sam początek wątku jest stosunkowo ciężkioperacja. Kod rozpoczyna pierwszy wątek, a następnie drugi. Pierwszy wątek, który został uruchomiony, kończy się, zanim drugi wątek uzyskał szansę na uruchomienie logiki biznesowej.


2 dla odpowiedzi nr 3

W przypadku wielowątkowości nie ma gwarancjiktóry wątek jest przydzielony na czas uruchomienia przez procesor, w takim przypadku wynik jest nieprzewidywalny i wygeneruje różne dane wyjściowe dla każdego uruchomienia.

Jeśli szukasz pożądanego wyjścia, potrzebujesz bloku synchronizacji. za pomocą wait i notify możesz to łatwo osiągnąć.

Spójrz na poniższą lekcję bezpośrednio z Oficjalna strona Oracle:

Uwaga: wait & notify musi zostać wywołany wewnątrz synchronized blokować i może wywoływać ten sam obiekt, na którym jest synchronizowany.

Przykładowy kod: (czytaj wbudowane komentarze)

public class Connor extends Thread {

private static Connor runner1 = new Connor();
private static Connor runner2 = new Connor();

public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("Hello " + i);

// wake up another thread to come out from wait state
if (runner1 == this) {
// wake up runner2
synchronized (runner2) {
runner2.notify();
}
} else {
// wake up runner1
synchronized (runner1) {
runner1.notify();
}
}

synchronized (this) {
try {
// say current thread to wait until notify by another thread
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

public static void main(String[] args) {
runner1.start();
runner2.start();
}
}

wydajność:

Hello 0
Hello 0
Hello 1
Hello 1
Hello 2
Hello 2
Hello 3
Hello 3
Hello 4
Hello 4
Hello 5
Hello 5
Hello 6
Hello 6
Hello 7
Hello 7
Hello 8
Hello 8
Hello 9
Hello 9

0 dla odpowiedzi nr 4

Dlaczego moje dane wejściowe pokazują, że jeden wątek działa po drugim, a nie w tym samym czasie?

Ogólne wyjaśnienie jest takie, że planowanie wątków jest nieprzewidywalne. Przeplatanie może zdarzyć się ... czy to może nie. Jest to fundamentalne dla wątków Java. (I rzeczywiście wątki w większości innych języków).

Jeśli potrzebujesz wykonania wątku do przeplotu w plikucałkowicie przewidywalny sposób, musisz wdrożyć jakiś mechanizm drżenia ręki, w którym jeden wątek czeka na inny i coś zrobi. Jest to jednak skomplikowane i zwykle nie pozwala na zastosowanie wątków.

FWIW: Odpowiedź @Braj pokazuje, w jaki sposób możesz wdrożyć ścisłe przeplatanie. Pamiętaj jednak, że oznacza to, że w danym momencie będzie wykonywany tylko jeden wątek. Ponadto oczekiwanie / powiadomienie spowoduje wiele pracy dla wątku harmonogram ... niektóre, że aplikacja będzie działać znacznie wolniej niż gdybyś właśnie wykonał pracę nad jednym wątkiem.


W tym konkretnym przykładzie występują dwa problemy, które sprawiają, że jakiekolwiek krótkotrwałe przeplatanie jest mało prawdopodobne:

  1. Tworzenie nowego macierzystego wątku w Javie tostosunkowo drogie, ponieważ zazwyczaj pociąga za sobą żądanie bloku pamięci od systemu operacyjnego do przechowywania stosu wątków. To z kolei pociąga za sobą „bałaganowanie” przez system operacyjny tabel stron, zerowanie bloku pamięci i tak dalej.

  2. Natywne planowanie wątków jest realizowane przezsystem operacyjny i działa na dość gruboziarnistym poziomie ... ponieważ jest to najbardziej wydajny sposób działania z perspektywy typowej aplikacji. (Przełączanie „kontekstów” wątku na komputerze klasy PC jest stosunkowo kosztowną operacją, a sam program do planowania wątków może potencjalnie mieć coś do zrobienia.)

W twoim przykładzie są szanse, że pierwszy wątek może powiedzieć „cześć” dziesięć razy, zanim drugi wątek będzie gotowy do zaplanowania.