Wątki Threads
Wątki (Threads) Concurrent programming is like stepping into an entirely new world and learning a new programming language!!! (grząski grunt) Unikaj jeśli możesz rozwiazać problem! Implementacja oparta zwykle na wielozadaniowym SO (dlatego brak JVM dla DOS, w3.1)
Potrzeby One of the most compelling reasons for concurrency is to produce a responsive user interface. Twój program realizuje eksperyment, masz na GUI przycisk <quit>? Sprawdzasz jego stan co pewien odcinek czasu?
Przetwarzanie równoległe i współbieżne
Cechy programowania wątkowego Zachowanie wątków jest zależne od platformy program wielowątkowy może być wolniejszy! W Javie mamy 10 poziomów priorytetu (Solaris 2 31, NT 7) Thread.MAX_PRIORITY, Thread.NORM_PRIORITY, Thread.MIN_PRIORITY A thread can be preempted at any time by another thread
Szeregowanie rotacyjne
Przeplot czasowy
Klasa Thread Klasa Thread nie jest wątkiem! Klasa może być kontrolerem wątku Z faktu że zdefiniujemy jakąś metodę w klasie pochodnej od Thread nie oznacza, że działa ona w osobnym wątku!
Thread c.d. start( ) //special initialization and then calls run( ). output for one run of this program will be different from that of another!!! thread scheduling mechanism is not deterministic!
Pierwszy sposób class simplethread extends Thread { public SimpleThread (String s) { super(s) ; public void run() { for (int i=0; i<10; i++) { System.out.println(i+ getname());...
Przykład wykorzystania class ThreeThreads {... main(string[] args) { new SimpleThread( Pierwszy ).start() ; new SimpleThread( Drugi ).start() ; new SimpleThread( Trzeci ).start() ;
2 sposób Interfejs Runnable Obiekt, który chce być kontrolerem wątku (określać co wątek ma robić) powinien wskazać że dysponuje odpowiednią metodą wykonawczą deklarując implementację interfejsu Runnable w którym zdefiniowano metodę: public interface Runnable { abstract public void run(); Obiekty klas implementujących interfejs Runnable możemy określić jako wykonywalne (aktywne) gdyż mogą być podstawą do uruchomienia wątku Każdy obiekt może być kontrolerem wątku (klasa może implementować dowolna liczbę interfejsów)
Przykład class Animation implements Runnable {... public void run() { while ( true ) { // Draw Frames... repaint(); Animation happy = new Animation("Mr. Happy"); Thread mythread = new Thread( happy ); mythread.start();...
Przykład
Usypianie wątku try { Thread.sleep ( 1000 ); catch ( InterruptedException e ) {
Zakończenie wątku Wątek kończy działanie gdy wystąpi jeden z trzech przypadków: returns from its target run() method interrupted by an uncaught exception before Java 1.2 its stop() method is called public final void stop() Deprecated. This method is inherently unsafe.
run() public void run() { while(true) { System.out.println(this); if(--countdown == 0) return; try { sleep(100); catch (InterruptedException e) { throw new RuntimeException(e);
Thread states NEW A thread that has not yet started is in this state. RUNNABLE A thread executing in the Java virtual machine is in this state. BLOCKED A thread that is blocked waiting for a monitor lock is in this state. WAITING A thread that is waiting indefinitely for another thread to perform a particular action is in this state. TIMED WAITING A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state. TERMINATED A thread that has exited is in this state.
Model stanów
Synchronizacja wątków Synchronizacja wątków w języka Java bazuje na koncepcji monitorów opracowanej przez C.A.R. Hoare. Monitor spełnia rolę zamka związanego z współużytkowanym zasobem. Jeśli zasób jest wolny obejmujesz go (drzwi otwarte wchodzisz i zamykasz). Po zakończeniu używania zwalniasz (otwierasz, wychodzisz następna osoba może skorzystać). Jeśli zasób jest zajęty wątek musi czekać. Monitory związane są z obiektami. Słowo kluczowe synchronized służy do oznaczenia miejsca, w którym wątek musi objąć monitor. Oznaczona tym słowem aktywność wykonuje się niepodzielnie*
Metody synchronizowane class SpreadSheet { int cella1, cella2, cella3; synchronized int sumrow() { return cella1 + cella2 + cella3; synchronized void setrow( int a1, int a2, int a3 ) { cella1 = a1; cella2 = a2; cella3 = a3;...
Synchronizowany blok synchronized ( myobject ) { // Functionality that needs to be synced... synchronized void mymethod () {... is equivalent to: void mymethod () { synchronized ( this ) {...
wait() notify() By executing wait() from a synchronized block, a thread gives up its hold on the lock and goes to sleep. A thread might do this if it needs to wait for something to happen in another part of the application. Later, when the necessary event happens, the thread that is running it calls notify() from a block synchronized on the same object. Now the first thread wakes up and begins trying to acquire the lock again.
Problem Producent - konsument class Producer extends Thread { static final int MAXQUEUE = 5; private Vector messages = new Vector(); public void run() { try { while ( true ) { putmessage(); sleep( 1000 ); catch( InterruptedException e ) {...
Konsument class Consumer extends Thread {... public void run() { try { while ( true ) { String message = producer.getmessage(); System.out.println("Got message: " + message); sleep( 2000 ); catch( InterruptedException e ) {
putmessage() private synchronized void putmessage() throws InterruptedException { while ( messages.size() == MAXQUEUE ) wait(); messages.addelement( new java.util.date().tostring() ); notify();
getmessage() // Called by Consumer public synchronized String getmessage() throws InterruptedException { notify(); while ( messages.size() == 0 ) wait(); String message = (String)messages.firstElement(); messages.removeelement( message ); return message;
??? Gdzie powinny być umieszczone metody getmessage() i putmessage() Literatura pomocnicza: M. Ben_Ari, Podstawy programowania współbieżnego, WNT Warszawa 1989
Wątki w komponencie public class Kompas extends Component implements Runnable {... Int azymut, newazymut ; Thread compasthread ; public Kompas(int azymut) { // konstruktor this.azymut = this.newazymut = azymut ; compasthread = new Thread(this); compasthread.start(); //end of constructor
Metoda run() public void run () { while(true) { if (newazymut!= azymut ) { try { Thread.currentThread().sleep(100); catch (InterruptedException e) { // obsługa błędu azymut++; azymut %=360; repaint(); //end of while
Setter public void setazymut (int newazymut) { this.newazymut = newazymut; // repaint(); Thread does it instead
Źródło impulsów - założenia public interface PulseSource { final static byte BURST_MODE = 0; final static byte CONTINOUS_MODE = 1; void addpulselistener(pulselistener pl); void removepulselistener(pulselistener pl); void trigger() ; // start generacji impulsów void setmode(byte mode) ; byte getmode() ; void halt() ; // zatrzymaj generację void setpulsedelay(int ms) ; int getpulsedelay() ; void setpulsecount(int burst) ;
Źródło impulsów public class PulseGenerator extends Thread implements PulseSource byte mode ; boolean on ;... public PulseGenerator() { mode = PulseSource.BURST_MODE ; start() ;
Źródło impulsów public void run() { while (on) { // fire up pulse event // test mode & check if last pulse // sleep for a moment public void halt() { on = false ; public void trigger() {???