Download presentation
Presentation is loading. Please wait.
Published byFrederica Kristin Mathews Modified over 9 years ago
1
Modernās Programmēšanas Tehnoloģijas (Advanced Programming Technologies) Edgars Celms, Mārtiņš Opmanis (askola@mii.lu.lv) Latvijas Universitātes Matemātikas un informātikas institūts 2007, Rīga, Latvija
2
Daudzpavedienu (multithreading) programmēšana valodā JAVA “Java™ How to Program, Sixth Edition” Chapter 23. Multithreading Pavedienu stāvokļi, pavedienu dzīves cikls Pavedienu prioritātes un to aktivēšana (scheduling) Pavedienu izveidošana un izpilde Pavedienu sinhronizācija Daudzpavedienu programmēšana un GUI Pakotne java.util.concurrent Monitori valodā JAVA
3
Ievads Daudzpavedienu programmēšana (multithreading) Nodrošina lietojumprogrammām iespēju strādāt ar daudziem izpildes pavedieniem (threads of execution) Dod iespēju programmai izpildīt uzdevumus paralēli Šādi programmējot bieži rodas nepieciešamība pēc pavedienu sinhronizācijas, lai nodrošinātu vēlamo funkcionalitāti
4
Dažas piezīmes I (Software Engineering Observation) A problem with single-threaded applications is that lengthy activities must complete before other activities can begin. In a multithreaded application, threads can be distributed across multiple processors (if they are available) so that multiple tasks are performed concurrently and the application can operate more efficiently. Multithreading can also increase performance on single-processor systems that simulate concurrency – when one thread cannot proceed, another can use the processor. Unlike languages that do not have built-in multithreading capabilities (such as C and C++) and must therefore make nonportable calls to operating system multithreading primitives, Java includes multithreading primitives as part of the language itself and as part of its libraries. This facilitates manipulating threads in a portable manner across platforms.
5
Pavedienu stāvokļi, pavedienu dzīves cikls Pavedienu stāvokļi (thread states) new stāvoklis Pavediens sāk savu dzīves ciklu ar new state Atrodas šajā stāvoklī līdz tam brīdim kad programma to startē un “pārved” to runnable stāvoklī runnable stāvoklis Pavediens šajā stāvoklī izpilda savu uzdevumu waiting stāvoklis Pavediens nonāk šai stāvoklī ja tam ir jāgaida uz kādu citu pavedienu līdz tas paveiks kādu uzdevumu timed waiting stāvoklis Pavediens nonāk šai stāvoklī ja tam ir jāgaida uz kādu citu pavedienu vai arī tam ir jāgaida uz laika intervālu kurā tas varētu izpildīties Pavediens no šī stāvokļa atgriežas runnable stāvoklī, ja tas saņem signālu no cita pavediena vai arī sagaida savu laika intervālu terminated stāvoklis runnable stāvoklī esošs pavediens nonāk šajā stāvoklī pēc sava uzdevuma izpildīšanas
6
Pavedienu stāvokļi, pavedienu dzīves cikls Pavedienu dzīves cikls attēlots ar UML stāvokļu diagrammu (state diagram)
7
Pavedienu stāvokļi, pavedienu dzīves cikls Operāciju sistēmas skats uz pavediena runnable stāvokli ready stāvoklis Pavediens šajā stāvoklī negaida uz citu pavedienu, bet gan gaida kamēr operāciju sistēma izdalīs procesora laiku running stāvoklis Pavedienam šajā stāvoklī tiek reāli izpildīts (izmanto procesora laiku) A thread in the running state often executes for a small amount of processor time called a time slice or quantum before transitioning back to the ready state Operating system’s internal view of Java’s runnable state
8
Pavedienu prioritātes un to aktivēšana (Thread Priorities and Thread Scheduling) Prioritātes Katram Javas pavedienam ir prioritāte Prioritātes ir robežās no MIN_PRIORITY (vērtība 1) un MAX_PRIORITY (vērtība 10) Pavedieni ar lielāku prioritāti ir “svarīgāki” un piekļūs procesora resursiem pirms pavedieniem ar zemāku prioritāti Prioritāte pēc noklusēšanas ir NORM_PRIORITY (konstante 5) Pavedienu aktivētājs (thread scheduler) Nosaka kuram pavedienam ir jāstrādā kā nākamajam Vienkāršākā implementācija ir tā saucamais apļkārtes (round-robin) princips vienādas prioritātes pavedieniem Augstākas prioritātes pavedieni var “pārpirkt (pārņemt)” (preempt) tekošo running stāvoklī esošu pavedienu Dažos gadījumos augstākas prioritātes pavedieni var nedefinēti aizkavēt zemākas prioritātes pavedienus – tiek saukta arī par “badošanos” (starvation)
9
Dažas piezīmes II (Software Engineering Observation) Thread scheduling is platform dependent – an application that uses multithreading could behave differently on separate Java implementations. When designing applets and applications that use threads, you must consider the threading capabilities of all the platforms on which the applets and applications will execute. Thread-priority scheduling.
10
Pavedienu izveidošana un izpilde Runnable interfeiss Izmanto, lai veidotu daudzpavedienu lietojumprogrammas Deklarē run metodi Izpilda objekts kurš implementē Executor interfeisu Executor interfeiss Deklarē execute metodi Izveido un pārvalda pavedienu grupu – tiek saukta par thread pool ExecutorService interfeiss Executor apakšinterfeiss kurā ir deklarētas citas metodes, kuras pārvalda Executor dzīves ciklu Objektus var radīt izmantojot atbilstošās klases Executors static metodes Metode shutdown pabeidz pavedienus ja uzdevumi ir pabeigti Executors klase Metode newFixedThreadPool izveido thread pool no fiksēta skaita pavedieniem Metode newCachedThreadPool izveido thread pool, kurš rada jaunus pavedienus pēc vajadzības
11
Implement runnable to create separate thread
12
Declare run method to fulfill interface Invoke static method sleep of class Thread to place the thread into the timed waiting state. At this point, the thread loses the processor, and the system allows another thread to execute. When the thread awakens, it reenters the runnable state
13
Create three PrintTask s; each will run in a separate thread Create fixed thread pool to execute and manage threads Execute each task; this method will assign a thread to the runnable Shutdown thread pool when runnable s complete their tasks
15
Pavedienu sinhronizācija (thread synchronization) Pavedienu sinhronizācija Valodā Java programmētājam tiek dota iespēja izmantot mutual exclusion mehānismu Dod iespēju ekskluzīvi (vienam pašam) strādāt ar kopīgiem (shared) objektiem Mutual exclusion (often abbreviated to mutex) algorithms are used in concurrent programming to avoid the simultaneous use of un-shareable resources by pieces of computer code called critical sections. Javā tas tiek implementēts izmantojot aiztures (locks) Lock interfeiss lock metode uzstāda aizturi (lock) un iedarbina mutual exclusion unlock metode atbrīvo aizturi (lock) Klase ReentrantLock implementē Lock interfeisu The constructor for a ReentrantLock takes a boolean argument that specifies whether the lock has a fairness policy. If this is set to true, the ReentrantLock's fairness policy states that the longest-waiting thread will acquire the lock when it is available. If this is set to false, there is no guarantee as to which waiting thread will acquire the lock when it is available.
16
Pavedienu sinhronizācija (thread synchronization) Nosacījuma mainīgie (condition variables) Ja pavediens, kuram ir aizture (holding the lock) nevar izpildīt savu uzdevumu dēļ tā, ka kāds nosacījums nav izpildījies, tad pavediens var gaidīt līdz nosacījums ir izpildījies Nosacījuma mainīgos var izveidot izsaucot Lock metodi newCondition Tiek reprezentēts ar objektu kurš implementē Condition interfeisu Condition interfeiss Deklarē metodes await – liek pavedienam gaidīt signal – lai “pamodinātu” (wake up) gaidošo pavedienu signalAll – lai “pamodinātu” visus gaidošos pavedienus
17
Populārākās programmēšanas kļūdas I (Common Programming Error) Deadlock occurs when a waiting thread (let us call this thread1) cannot proceed because it is waiting (either directly or indirectly) for another thread (let us call this thread2) to proceed, while simultaneously thread2 cannot proceed because it is waiting (either directly or indirectly) for thread1 to proceed. Two threads are waiting for each other, so the actions that would enable each thread to continue execution never occur. It is an error if a thread issues an await, a signal, or a signalAll on a condition variable without having acquired the lock for that condition variable. This causes an IllegalMonitorStateException.
18
Dažas piezīmes II (Software Engineering Observation) When multiple threads manipulate a shared object using locks, ensure that if one thread calls method await to enter the waiting state for a condition variable, a separate thread eventually will call Condition method signal to transition the thread waiting on the condition variable back to the runnable state. If multiple threads may be waiting on the condition variable, a separate thread can call Condition method signalAll as a safeguard to ensure that all the waiting threads have another opportunity to perform their tasks. If this is not done, indefinite postponement or deadlock could occur. The locking that occurs with the execution of the lock and unlock methods could lead to deadlock if the locks are never released. Calls to method unlock should be placed in finally blocks to ensure that locks are released and avoid these kinds of deadlocks. Performance tip. Using a Lock with a fairness policy helps avoid indefinite postponement, but can also dramatically reduce the overall efficiency of a program. Because of the large decrease in performance, fair locks are only necessary in extreme circumstances. Performance tip. Synchronization to achieve correctness in multithreaded programs can make programs run more slowly, as a result of thread overhead and the frequent transition of threads between the waiting and runnable states.
19
Ražotāja/patērētāja attiecība (producer/consumer relationship) bez sinhronizācijas Ražotāja/patērētāja attiecība Ražotājs ģenerē datus un glabā tos kopīgā atmiņas apgabalā (shared memory) Patērētājs lasa saražotos datus no kopīgā atmiņas apgabala Kopīgo atmiņas apgabalu sauksim par buferi (buffer)
20
Implement the runnable interface so that producer will run in a separate thread Declare run method to satisfy interface
21
Sleep for up to 3 seconds
22
Implement the runnable interface so that producer will run in a separate thread Declare run method to satisfy interface
23
Sleep for up to 3 seconds
24
Shared variable to store data Set the value of the buffer Read the value of the buffer
25
Create shared UnsynchronizedBuffer for producer and consumer to use
26
Pass shared buffer to both producer and consumer
29
Ražotāja/patērētāja attiecība (producer/consumer relationship) ar sinhronizāciju Ražotāja/patērētāja attiecība ar sinhronizāciju Piemērā tiek izmantots Locks un Conditions, lai implementētu sinhronizāciju
30
Create ReentrantLock for mutual exclusion Create two Condition variables; one for writing and one for reading Buffer shared by producer and consumer Try to obtain the lock before setting the value of the shared data
31
Producer waits until buffer is empty
32
Signal consumer that it may read a value Release lock on shared data Acquire lock before reading a value
33
Consumer waits until buffer contains data to read
34
Signal producer that it can write to buffer Release lock on shared data
35
Create SynchronizedBuffer to be shared between producer and consumer
36
Execute the producer and consumer in separate threads
39
Populārākās programmēšanas kļūdas II (Common Programming Error) Place calls to Lock method unlock in a finally block. If an exception is thrown, unlock must still be called or deadlock could occur. Forgetting to signal a thread that is waiting for a condition is a logic error. The thread will remain in the waiting state, which will prevent the thread from doing any further work. Such waiting can lead to indefinite postponement or deadlock.
40
Dažas piezīmes III (Software Engineering Observation) Always invoke method await in a loop that tests an appropriate condition. It is possible that a thread will reenter the runnable state before the condition it was waiting on is satisfied. Testing the condition again ensures that the thread will not erroneously execute if it was signaled early.
41
Ražotāja/patērētāja attiecība (producer/consumer relationship) izmantojot riņķveda (circular) buferi Iepriekšējos piemēros neoptimāls laika sadalījums, ja plūsmas izpilda savus uzdevumus ar dažādiem ātrumiem Riņķveida buferis (circular buffer) Tiek nodrošināts kopīgs atmiņas apgabals (programmējama izmēra), kurā ražotājs var ievietot vērtības un patērētājs var šīs vērtības nolasīt
42
Dažas piezīmes IV (Software Engineering Observation) Performance tip.Even when using a circular buffer, it is possible that a producer thread could fill the buffer, which would force the producer thread to wait until a consumer consumes a value to free an element in the buffer. Similarly, if the buffer is empty at any given time, the consumer thread must wait until the producer produces another value. The key to using a circular buffer is to optimize the buffer size to minimize the amount of thread wait time.
43
Lock to impose mutual exclusionCondition variables to control writing and reading Circular buffer; provides three spaces for data Obtain the lock before writing data to the circular buffer
44
Wait until a buffer space is empty Update index; this statement imposes the circularity of the buffer Signal waiting thread it can now read data from buffer Release the lock
45
Lock the object before attempting to read a value Wait for a value to be written to the buffer Update read index; this statement imposes the circularity of the buffer
46
Signal thread waiting to write to the buffer Release the lock
48
Create CircularBuffer for use in both the producer and consumer Execute the producer and consumer in separate threads
52
Ražotāja/patērētāja attiecība (producer/consumer relationship) izmantojot ArrayBlockingQueue Klase ArrayBlockingQueue Riņķveida bufera implementācija valodā Java Implementē BlockingQueue interfeisu Deklarē metodes put un take, lai varētu rakstīt un lasīt datus buferī
53
Create instance of ArrayBlockingQueue to store data Place a value into the buffer; blocks if buffer is full
54
Remove value from buffer; blocks if buffer is empty
55
Create BlockingBuffer for use in producer and consumer Execute the producer and consumer in separate threads
57
Daudzpavedienu programmēšana un GUI Swing GUI komponentes Nav pavedienu drošas Izmaiņas ir jāveic event-dispatching pavedienā (tiek saukts arī par event-handling pavedienu) Lai realizētu var lietot klases SwingUtilities static metodi invokeLater nododot tai objektu, kurš implementē Runnable interfeisu
58
Implement the Runnable interface Lock to implement mutual exclusion Condition variable for suspending the threads Boolean to control whether thread is suspended Create the Lock and a Condition variable Get name of current thread
59
Obtain the lock to impose mutual exclusion Wait while thread is suspended Release the lock
60
Call invokeLater Method invokeLater is passed a Runnable
61
Obtain lock for the applicationResume a waiting threadRelease the lock
62
Create Lock for the application
63
Create thread pool for executing threads
64
Execute a Runnable Shutdown thread pool when threads finish their tasks
66
Dažas piezīmes V (Software Engineering Observation) The Runnable interface provides only the most basic functionality for multithreaded programming. In fact, this interface has several limitations. Suppose a Runnable encounters a problem and tries to throw a checked exception. The run method is not declared to throw any exceptions, so the problem must be handled within the Runnable. The exception cannot be passed to the calling thread. Now suppose a Runnable is performing a long calculation and the application wants to retrieve the result of that calculation. The run method cannot return a value, so the application must use shared data to pass the value back to the calling thread. This also involves the overhead of synchronizing access to the data. The developers of the new concurrency APIs in J2SE 5.0 recognized these limitations and created a new interface to fix them. The Callable interface (package java.util.concurrent) declares a single method named call. This interface is designed to be similar to the Runnable interface allowing an action to be performed concurrently in a separate thread but the call method allows the thread to return a value or to throw a checked exception.
67
Citas klases java.util.concurrent pakotnē Callable interfeiss Deklarē call metodi Metode call dod iespēju paralēlam uzdevumam atgriezt vērtību vai arī izveidot izņēmumgadījuma situāciju (throw an exception) ExecutorService metodei submit ir Callable parametrs un tā atgriež Future, kas reprezentē uzdevuma rezultātu Future interfeiss Deklarē get metodi Metode get atgriež uzdevuma rezultātu
68
Monitori valodā JAVA (monitors and monitor locks) Monitori (monitors) Katram Javas objektam ir monitors Atļauj vienlaicīgi izpildīties tikai vienam pavedienam synchronized instrukcijas iekšienē synchronized ( object ) { statements } // end synchronized statement Pavedieni kuri gaida, lai iegūtu monitora aizturi (lock) tiek novietoti blocked stāvoklī Object metode wait novieto pavedienu waiting stāvoklī Object metode notify “pamodina” waiting stāvoklī esošu pavedienu Object metode notifyAll “pamodina” visus waiting stāvoklī esošus pavedienus Javā ir iespējamas arī sinhronizētas metodes (synchronized methods). Sinhronizēta metode ir ekvivalenta tam, ja synchronized instrukcija būtu iekļāvusi visu metodes ķermeni
69
Dažas piezīmes VI (Software Engineering Observation) The locking that occurs with the execution of synchronized methods could lead to deadlock if the locks are never released. When exceptions occur, Java’s exception mechanism coordinates with Java’s synchronization mechanism to release locks and avoid these kinds of deadlocks.
70
Populārākās programmēšanas kļūdas III (Common Programming Error) It is an error if a thread issues a wait, a notify or a notifyAll on an object without having acquired a lock for it. This causes an IllegalMonitorStateException.
71
Declare a synchronized set method Wait until buffer is emptySet buffer value
72
Buffer is now occupied Notify waiting thread that it may now read a value Declare synchronized get method Wait until buffer is full
73
Buffer is now empty Notify thread it may now write to buffer
74
Create SynchronizedBuffer for use in producer and consumer Execute the producer and consumer in separate threads
77
Jautājumi ?
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.