Programowanie współbieżne

Programowanie w Javie polega w zasadzie na określaniu instrukcji, które mają się kolejno wykonywać, jedna po drugiej, od góry do dołu, w kolejności umieszczenia w pliku kodu źródłowego. My, programując, określamy jakie to mają być instrukcje, a coś – w przypadku Javy będzie to Wirtualna Maszyna Javy -, te instrukcje wykonuje.

Pierwszą instrukcją programu jest pierwsza instrukcja metody głównej main(…) a ostatnią jej instrukcja ostatnia. Oczywiście będziemy z metody main(…) wywoływali różne inne metody (tej samej lub innych klas), ale nadal wszystko będzie wykonywane w ustalonej kolejności, instrukcja po instrukcji. Wszystkie instrukcje naszego programu będą wykonane w jednej sekwencji. Mówiąc językiem programowania współbieżnego – w jednym wątku.

Jednak w świecie rzeczywistym wiele rzeczy dzieje się naraz, niezależnie od siebie. Wiele rzeczy dzieje się naraz w świecie rzeczywistym i wiele rzeczy potrzebuje się dziać naraz, niezależnie od siebie, w aplikacjach które w tym świecie funkcjonują. Nowoczesne języki programowania, w tym Java, umożliwiają tworzenie takich wielowątkowych aplikacji. W aplikacjach tych określamy już nie jedną sekwencję instrukcji, ale kilka, dowolnie wiele, z których każda może wykonywać się niezależnie od siebie, nijako w tym samym czasie, tzn. współbieżnie.

Ciąg instrukcji zapisanych w metodzie main(…) definiuje instrukcje, które będą wykonane w ramach tzw. głównego wątku. Kod metody main(…) to definicja wątku, który to wątek uruchamiany jest wraz z uruchomieniem programu. Uruchomienie programu to de facto uruchomienie tego głównego wątku.

Jeśli chcemy aby jakiś inny kod (ciąg instrukcji) wykonywał się niezależnie od kodu wątku głównego, tj. współbieżnie z nim, to po pierwsze musimy określić jaki to kod, a po drugie musimy go uruchomić. Kod wątku głównego określamy implementując metodę main(…); kod innych wątków implementując dowolną klasę dziedziczącą z klasy java.lang.Thread albo klasę która implementuje interfejs java.lang.Runnable. Mamy więc dwie możliwości, jednak w obydwu przypadkach implementacja wątku sprowadza się do implementacji metody run().

Aby zdefiniować wątek – którego jedyną instrukcją będzie wyświetlenie tekstu powitalnego – poprzez implementację klasy dziedziczącej z klasy Thread moglibyśmy napisać:

class MyThread extends Thread {
  public void run() {
    System.out.println("Witaj w świecie programowania współbieżnego!");
  }
}

Klasa MyThread dziedziczy z klasy Thread, tak więc jest definicją wątku, ale samo zaimplementowanie tej klasy jeszcze nie powoduje że kod ten się wykona. Uruchamiając program uruchamiamy tylko wątek główny, tj. kod zapisany w metodzie main(…), a żeby uruchomić wątek zaimplementowany w postaci klasy MyThread musimy utworzyć instancję tej klasy i uruchomić dla niej metodę start(). Kod który to zrobi musimy naturalnie umieścić pośród instrukcji wątku głównego (albo jakiegoś innego wątku uruchomionego z wątku głównego). Moglibyśmy więc napisać:

public class TestClass {
  public static void main(String[] args) {
    Thread newThread = new MyThread();
  
    newThread.start();
  }
}

Metoda start() odziedziczona przez klasę MyThread z klasy Thread tworzy nowy wątek Wirtualnej Maszyny Javy i uruchamia w jego ramach kod zdefiniowany w metodzie run(). Od tej chwili mamy dwa aktywne, współbieżnie wykonujące się ciągi instrukcji, tzn. wątki – wątek główny (który nic nie robi poza uruchomieniem kolejnego wątku) oraz wątek zdefiniowany poprzez klasę MyThread.

0 0 votes
Daj ocenę
Subscribe
Powiadom o
guest

1 Komentarz
najstarszy
najnowszy oceniany
Inline Feedbacks
View all comments