RINNAKKAISTA OHJELMOINTIA JAVA-KIELELLÄ

Koko: px
Aloita esitys sivulta:

Download "RINNAKKAISTA OHJELMOINTIA JAVA-KIELELLÄ"

Transkriptio

1 RINNAKKAISTA OHJELMOINTIA JAVA-KIELELLÄ Tässä dokumentissa esitellään Java-kielisen rinnakkaisen ohjelmoinnin perusteet kurssin A Ohjelmiston rakentaminen tarpeisiin. Aluksi käsitellään lyhyesti rinnakkaista ohjelmointia yleisesti. Toisessa kappaleessa perehdytään Javan rinnakkaisuuden perusominaisuuksiin ja kolmannessa rinnakkaisessa ohjelmoinnissa esiintyviin tyypillisin malleihin tuottaja-kuluttajamalli sekä lukijakirjoittajamalli. Tämän jälkeen esitellään lyhyesti eloisuusongelmia ja viimeisessä kappaleessa tutustutaan joihinkin Javan korkeamman tason rinnakkaisuuden hallinnan mekanismeihin. Rinnakkaisuuden ominaisuuksiin käyttöjärjestelmän näkökulmasta voi tutustua esimerkiksi teoksesta [Sil]. 1. Johdanto rinnakkaisuuteen Peräkkäinen ohjelma (sequential program) koostuu toisiaan seuraavista käskyistä, joita suoritetaan peräkkäin, kunnes ohjelma päättyy. Peräkkäisellä ohjelmalla on selkeä suorituspolku ja se on deterministinen, ts. samalla syötteellä ohjelma antaa aina saman tuloksen. Rinnakkainen ohjelma (concurrent program, parallel program) sen sijaan suorittaa kahta tai useampaa toimintaa yhtä aikaa. Rinnakkaisella ohjelmalla ei ole yhtä suorituspolkua ja sen antama tulos voi riippua myös toimintojen suoritusjärjestyksestä. Lähes kaikki nykyiset tietokoneohjelmat ovat jossain määrin rinnakkaisia; graafisen käyttöliittymän toiminta perustuu nimittäin siihen, että käyttöjärjestelmä kuuntelee käyttöliittymään liittyviä tapahtumia ja ohjaa ne sitten suorittavalle ohjelmalle. Rinnakkainen ohjelma voidaan suorittaa Antamalla yhden prosessorin huolehtia eri toiminnoista (multiprogramming). Käyttöjärjestelmän on tuettava moniajoa. Antamalla kukin tehtävä eri prosessorin tai prosessoriytimen suoritettavaksi samassa koneessa (multiprocessing). Hajauttamalla eri toiminnot toisiinsa kytkettyihin koneisiin (distributed programming). Kahdessa jälkimmäisessä tapauksessa on kysymys aidosta, fyysisestä rinnakkaisuudesta. Ensimmäisessä tapauksessa rinnakkaisuus voi olla siinä mielessä harhaa, että yksi prosessori voi suorittaa vain yhden konekielisen käskyn kerrallaan. Tosin nykyään yhdessäkin prosessorissa on yleensä useampia ytimiä, jotka voivat suorittaa operaatioita aidosti rinnakkain. Siinäkin tapauksessa, että konekielisiä käskyjä suoritetaan yksi kerrallaan, käyttöjärjestelmä voi huolehtia siitä, että kukin toiminto saa keskusyksiköltä suoritusaikaa niin, että toiminnot suoritetaan rinnakkain. Tässä tapauksessa puhutaan myös loogisesta rinnakkaisuudesta. Tässä moduulissa keskitytään ensimmäisen tapauksen rinnakkaiseen ohjelmointiin (concurrent programming) Prosesseista ja säikeistä Prosessi on käyttöjärjestelmän tapa ajaa useita ohjelmia rinnakkain yhdessä prosessorissa yleensä yhtä prosessia vastaa yksi suoritettava ohjelma. Käyttöjärjestelmä takaa prosesseille jonkinasteisen riippumattomuuden muista prosesseista. Turvasyistä prosessit eivät saa yleensä jakaa muistialuetta. Näin ollen niiden välinen kommunikaatio pitää hoitaa muilla mekanismeilla (esimerkiksi putkilla). Prosessin ominaisuudet riippuvat käyttöjärjestelmästä. Yleisimmin prosessien suorittaminen perustuu aikajakoon: kukin prosessi keskeytetään aika ajoin ja toinen prosessi päästetään suoritukseen. 1

2 Prosessi voi elinkaarensa aikana olla seuraavissa tiloissa: Uusi (new) prosessi on luotu. Ajossa (runnning) prosessin koodia suoritetaan. Odotustilassa (waiting) prosessin suoritus on estetty, koska se odottaa jotakin tapahtumaa (IO tapahtuma, signaali jne.). Valmiustilassa (ready) prosessi on valmiina suoritukseen, kun se saa aikaa keskusyksiköltä. Lopetettu (terminated) prosessin suoritus on lopetettu. Käyttöjärjestelmä huolehtii prosessien skeduloinnista (scheduling) eli siitä, miten valitaan valmiustilassa oleva prosessi suoritukseen. Prosessin prioriteetti määrää sen, kuinka paljon prosessi saa suoritusaikaa muihin prosesseihin verrattuna. Prosessin keskeyttäminen vaatii aina sen keskeytyshetkisten ominaisuuksien tallentamisen, jotta prosessi saataisiin uudelleen asianmukaisesti suoritukseen. Prosessin ominaisuuksia (prosessin tila, CPU rekisterien arvot, muistinhallintatiedot jne.) säilytetään ns. prosessikontrollilohkossa (Process Control Block, PCB), joka tallennetaan prosessin keskeytyessä (ks. esim. [Sil], luku 4). Näin ollen moniajo kuluttaa ylimääräisiä resursseja. Prosessi on (erityisesti UNIXissa) raskaansarjan suoritusyksikkö. Yksittäinen ohjelma saadaan kevyemmin rinnakkaiseksi jakamalla se säikeisiin. Säie on peräkkäisesti toimiva käskyjono, joka toimii muista säikeistä riippumatta; säikeellä on oma ohjelmalaskuri ja pino. Saman prosessin säikeet käyttävät kuitenkin tämän prosessin muistialuetta ja käyttöjärjestelmän resursseja, ts. ne voivat käsitellä samoja tiedostoja sekä oheislaitteita. Säikeille annetaan suoritusaikaa samaan tapaan kuin prosesseillekin, paitsi että aikajako suoritetaan ohjelman saaman ajan puitteissa ja säikeet priorisoidaan ohjelmallisesti. Säikeiden yhteydenpito voi tapahtua kuten prosessienkin, mutta lisäksi niillä on yhteinen muistialue, jota voidaan käyttää kommunikaatiossa. Säikeen luominen kuluttaa aikaa keskimäärin kolmasosan uuden prosessin luomisesta. Säikeiden luomiselle ja synkronoinnille käyttöjärjestelmätasolla on olemassa standardi (POSIX : IEEE standardit, osa ). Standardissa kuvataan säikeen käyttäytyminen, ei kuitenkaan itse toteutusta. Standardia luotaessa 1990-luvun puolivälissä syntyi myös C-kielinen standardikirjasto Pthreads (POSIX threads). Tässä moduulissa keskitytään käytännön toteutuksessa Javan säikeisiin, jotka pääsääntöisesti noudattelevat mainittua standardia. Joitakin poikkeuksia tosin on, erityisesti säikeiden odottamisen (waiting) ja ilmoittamisen (notification) toteutuksessa. Huomaa, että jokainen ohjelma koostuu ainakin yhdestä säikeestä, kaikissa ohjelmissa on pääohjelma, joka on säie. 2

3 1.2. Rinnakkaisuuden ongelmia Ohjelman kirjoittaminen rinnakkaiseksi tuo mukanaan monia etuja, ohjelman vasteajat saadaan optimoitua, ohjelma voi suorittaa IO-toimintoja samaan aikaan laskennallisten operaatioiden kanssa, ohjelma voi kommunikoida useiden muiden ohjelmien kanssa jne. Rinnakkaisuus tuo myös mukanaan useita ongelmia, joita ei esiinny peräkkäisissä ohjelmissa. Rinnakkaisen ohjelman oikeellisuuskriteerit voidaan jakaa kahteen pääkategoriaan (ks. [Lea] 1.3): Turvallisuus (safety) o Olioille ja muuttujille ei tapahdu mitään epätoivottua Eloisuus (liveness) o Kaikki tarkoitetut toimenpiteet suoritetaan joskus Turvallisuus Rinnakkaisessa ohjelmoinnissa hyvin yksinkertaisetkin operaatiot voivat mennä vikaan suoritusjärjestyksen muuttuessa. Oletetaan esimerkiksi, että kaksi säiettä S1 ja S2 suorittavat samalle kokonaislukumuuttujalle x operaation x = x+1. Toivottu lopputulos on muuttujan x arvon kasvaminen kahdella. Kuitenkin tietokone suorittaa operaation x = x+1 niin, että muuttujan arvo luetaan ensin muistipaikasta rekisteriin, rekisterin arvoa kasvatetaan ja sitten uusi arvo kopioidaan rekisteristä muistipaikkaan. Näin ollen operaatio ei ole atomaarinen. Jos säikeet S1 ja S2 suorittavat operaationsa peräkkäin, saadaan haluttu lopputulos, mutta koska S1 ja S2 toimivat toisistaan riippumatta, voi suoritusjärjestys olla esimerkiksi seuraava: S1 : lue x S2 : lue x S1 : x = x+1 S1 : kirjoita x S2 : x = x+1 S2 : kirjoita x Operaation tuloksena muuttuja x kasvaa vain yhdellä, mikä ei ole toivottu lopputulos. Vastaavalla tavalla metodi voi palauttaa ennalta-arvaamattomia arvoja jos kaksi säiettä kutsuu sitä rinnakkain. Metodia, joka toimii millä tahansa kutsujärjestyksellä oikein, sanotaan säieturvalliseksi (thread safe). Edelleen muuttujan tai muun tallennusrakenteen samanaikainen kirjoittaminen ja lukeminen voi tuottaa kummallisia arvoja, samoin kuin kahden säikeen yhtäaikainen kirjoittaminen samaan muuttujaan. Tällaisia virhetilanteita sanotaan kilpailutilanteiksi; englanninkielisissä lähteissä edellä mainituista virhetilanteista käytetään nimitystä race condition. 3

4 Eloisuus Turvallisen, ts. konflikteista vapaan, ohjelman voi kirjoittaa käyttämällä ainoastaan yhtä säiettä. Tällä tavalla menetetään kuitenkin rinnakkaisuuden edut. Näin ollen turvallisuus ja eloisuus ovat usein suunnittelussa vastakkaisissa vaakakupeissa. Eloisassa ohjelmassa kaikki aiotut operaatiot suoritetaan joskus; huomaa että mitään aikarajaa ei kuitenkaan aseteta. Reaaliaikaisessa ohjelmoinnissa on yleensä asetettu maksimiaikoja operaatioiden kestolle. Yleisimmin operaatio jää suorittamatta, koska sen säie odottaa jonkin resurssin vapautumista. Tällaisia tapauksia voivat olla: toinen säie on lukinnut metodin, jota yritetään suorittaa, metodi lukkiutuu odottaen toisen säikeen suorittamaa tapahtumaa, metodi odottaa IO-toimintoa (toisesta prosessista tai laitteesta), jotkin toiset säikeet tai ohjelmat käyttävät kaikki keskusyksikköresurssit. Lisäksi operaatio saattaa jäädä suorittamatta jonkin ajonaikaisen virheen tai poikkeuksen takia. Listassa mainituista ongelmista selvitään yleensä yrittämällä suorittaa operaatio, kunnes se onnistuu. Joskus kuitenkin ohjelma voi ajautua tilaan, jossa operaation suoritus on mahdoton pysyvästi. Tällainen tilanne voi olla Lukkiutuminen (deadlock) o Säie S1 on lukinnut olion X ja yrittää lukita oliota Y; samanaikaisesti säie S2 on lukinnut olion Y ja yrittää lukita oliota X. Tällöin kumpikaan säie ei pääse etenemään. Tämä voi tapahtua myös useammalle säikeelle syklisesti. Signaalin menettäminen (missed signal) o Säie jää odottamaan, koska se on alkanut odottaa vasta sen jälkeen kun sen heräämiseksi tarkoitettu signaali on tuotettu. Sisäkkäisten monitorien lukkiutuminen (nested monitor lockout) o Säie itse on lukinnut metodin, jota tarvitaan sen herättämiseksi. Vauhkoontuminen (livelock) o Säie yrittää toistaa operaatiota, joka on tuomittu epäonnistumaan. Nälkiintyminen (starvation) o Säie ei saa lainkaan keskusyksiköltä ajoaikaa (voi johtua useista syistä). Hajauttamisen epäonnistuminen (distributed failure) o Kone, johon ollaan yhteydessä verkon yli, kaatuu tai yhteys siihen katkeaa. Eloisuuteen liittyy läheisesti suorituskyky, jota voidaan mitata erilaisin kriteerein. Vaikka tarkkoja aikarajoja ohjelman suorittamille operaatioille ei asetettaisikaan, on selvää, että lähes jokaisen ohjelman on noudatettava jonkinlaisia suorituskykykriteerejä. Suorituskyvyn mittareita ovat esimerkiksi Tuotos (throughput) o Aikayksikössä suoritettujen operaatioiden lukumäärä. Usein esitetään myös operaatioon kuluvana aikana. Viive (latency) o Viestin lähettämisen ja sen suorittamisen välinen aika. Yleensä käytetään mittaamaan vasteaikaa. Kapasiteetti (capacity) 4

5 o Yhtäaikaisesti suoritettavien tehtävien lukumäärä. Erityisesti verkkopohjaisissa sovelluksissa voidaan käyttää mittaamaan palvelun saatavuutta. Tehokkuus (efficiency) o Tuotoksen suhde laskentaresursseihin. Skaalattavuus (scalability) o Suhde jolla tuotos paranee, kun resursseja lisätään. Huonontuminen (degradation) o Suhde, jolla viive kasvaa tai tuotos huononee, kun asiakkaiden, operaatioiden tai toimintojen määrää kasvatetaan lisäämättä resursseja. Näistä skaalattavuus ja huonontuminen ovat hieman epämääräisiä käsitteitä eivätkä ole suoraan vertailukelpoisia ohjelmien välillä. Monisäikeinen ohjelma on yhdellä suoritinyksiköllä peräkkäistä ohjelmaa huonompi laskentateholla mitattuna, koska säikeiden luominen ja ylläpitäminen vievät resursseja. Näin ollen ohjelmaa, joka suorittaa vain yhtä laskennallista tehtävää, jota ei voi hajauttaa monessa prosessorissa tai ytimessä suoritettavaksi, ei kannata kirjoittaa rinnakkaiseksi. Sen sijaan ohjelma, jonka on kommunikoitava käyttäjän tai oheislaitteiden kanssa suoriutuu lähes aina rinnakkaisena tehtävästään paremmin kuin peräkkäisenä. Tärkeintä rinnakkaisten ohjelmien hallinnassa on ymmärtää rinnakkaisen ohjelman ja peräkkäisen ohjelman erot ja ne ongelmatilanteet, jotka rinnakkaisuus tuo mukanaan. On osattava kiinnittää huomio ohjelmien vaatimuksiin ja rajoituksiin ja on tarkasteltava onko jokin edellä mainituista virhetilanteista mahdollinen. 2. Rinnakkaisuuden perustoteutus Javassa Rinnakkaisia ohjelmia voidaan toteuttaa useilla ohjelmointikielillä. Java-kielellä on moniin muihin yleisiin kieliin verrattuna se etu, että se on alun perin suunniteltu tukemaan rinnakkaista ohjelmointia. Näin ollen rinnakkaisuus on Javassa sisäänrakennettuna ja rinnakkaisten ohjelmien kirjoittaminen sillä on luontevaa. Siksi tässä moduulissa käytetään ohjelmointikielenä Javaa. Lukijan oletetaan tuntevan Java-kielen ja olio-ohjelmoinnin perusteet. Seuraavassa esitetään rinnakkaisuuden toteuttamista varten välttämättömät Java-kielen rakenteet, joita ei oleteta tunnetuksi Java-ohjelman suorittamisesta Tietokoneohjelma on tietokoneen prosessorin ymmärtämien, binäärisessä muodossa olevien käskyjen joukko. Käskykanta on prosessorikohtainen, joten tekstimuodossa olevasta koodista on käännettävä konekielinen ohjelma. Tästä huolehtii tietokoneohjelma, jota kutsutaan kääntäjäksi. Tavallinen käännettävä ohjelma muodostetaan siis seuraavasti: OHJELMA.C kääntäjä OHJELMA.EXE Näin saatava suoritettava ohjelma on aina ympäristösidonnainen ja esimerkiksi PC:ssä käännettyä ohjelmaa ei voi suorittaa UNIX-ympäristössä. Javassa siirrettävyysongelma on ratkaistu niin, että tekstimuotoisesta koodista käännetään ensin tavukoodi, joka on laitteistoriippumaton. Tavukoodi talletetaan class-tunnisteisiin tiedostoihin niin, 5

6 että yksi tiedosto sisältää yhden luokan koodin. Javan virtuaalikone (Java Virtual Machine, JVM) muodostaa tavukoodista suoritettavan ohjelman (ks. esim. [Ven]). Jokaisessa ympäristössä on oma virtuaalikoneensa, joka suorittaa koodin; tämä mahdollistaa siirrettävyyden, mutta tekee myös Java -ohjelmista tyypillisesti hieman hitaampia kuin esimerkiksi C-ohjelmista. Seuraava kuvio havainnollistaa mekanismia, jolla lähdekielisestä Java-koodista muodostetaan suoritettava ohjelma: Kääntäjä LÄHDE- KOODI Luokkien lataaja Suorittaja (Execution engine) (Java compiler) (Class loader) TAVU- KOODI KONEKIELINEN OHJELMA Tavukoodin tarkastaja (Bytecode verifier) Kuva 1: Java-ohjelman suorittaminen Ohjelmaa suoritettaessa virtuaalikoneen luokkien lataaja (class loader) hakee ensin ohjelmaan liittyvien luokkien tavukoodit. Tämän jälkeen ne syötetään tavukoodin tarkastajalle (bytecode verifier), joka varmistaa, että tavukoodi on asianmukaisesti muodostettu ja voidaan suorittaa turvallisesti. Lopulta suorittaja (execution engine) tulkitsee ja suorittaa tavukoodin. Suorittaja voi olla tulkkipohjainen, mutta useimmissa toteutuksissa tulkkauksen hitautta suoritettavaan konekieliseen koodiin verrattuna kompensoidaan ns. JIT-käännöksellä (Just In Time compilation). JIT-kääntäjä tulkitsee metodin tavukoodin ympäristönsä konekieliseksi koodiksi välittömästi ennen kuin koodi suoritetaan ja tallentaa konekielisen koodin välimuistiin. Näin ollen metodia uudelleen kutsuttaessa voidaan suoraan käyttää sen konekielistä koodia. Javan virtuaalikone huolehtii myös rinnakkaisuuden hallinnasta, ts. säikeiden luomisesta ja niiden ajoituksesta jne. Tällaisten seikkojen toteutus on kuitenkin käyttöjärjestelmästä riippuva (siis siitä miten käyttöjärjestelmän tasolla toteutetaan säikeet ja niiden synkronointi), sillä Javan virtuaalikone voi joissakin järjestelmissä käyttää suoraan järjestelmän säikeitä. Näin ollen rinnakkaisten ohjelmien toiminnassa voi eri alustoilla olla tästä johtuvia eroja myös eri Java-toteutuksissa. Kaikissa ympäristöissä, joissa Java on toteutettu, on kuitenkin mahdollista rakentaa rinnakkaisia ohjelmia. 6

7 2.2. Javan säikeet Koska säikeet kuuluvat Javan perustoteutukseen, lähes kaikissa asianmukaisissa Java-kielen oppikirjoissa käsitellään myös monisäieohjelmointia, ks. esimerkiksi [Arn] tai [Ves]. Verkossa on myös lukuisia esityksiä Javan rinnakkaisen ohjelmoinnin perusteista, esimerkiksi sivut ja ovat tutustumisen arvoisia. Käyttöjärjestelmä voi tukea säikeitä kahdella tavalla: käyttäjätason toteutuksessa puhutaan käyttäjäsäikeistä (user threads) ja käyttöjärjestelmän ytimen tasolla ydinsäikeistä (kernel threads). Käyttäjäsäikeille tarjoaa tuen säiekirjasto, joka hoitaa säikeiden ajastuksen niin, että käyttöjärjestelmän ytimen ei tarvitse puuttua asiaan. Käyttöjärjestelmän ydin tukee suoraan ydinsäikeitä, ts. ydin luo säikeet, ajastaa ja hallitsee niitä. Useimmat nykyiset käyttöjärjestelmät käyttävät ydinsäikeitä. Koska Javassa säikeitä hallitsee Javan virtuaalikone, Javan säikeet eivät varsinaisesti kuulu kumpaakaan yllä mainittuun päätyyppiin. Säikeiden toteuttamista käyttöjärjestelmätasolla ja sen yhteyttä Javan säikeisiin käsitelllään tarkemmin teoksessa [Sil], luku 5. Javan säikeet jaetaan kahteen luokkaan: Käyttäjäsäikeet (user threads) o Varsinaiset säikeet Taustasäikeet (daemon threads) o Taustalla toimivat säikeet Lisäksi jokaisella säikeellä on prioriteetti; korkean prioriteetin säikeet saavat suorituksessa etusijan alhaisen prioriteetin säikeisiin nähden. Kun Javan virtuaalikone käynnistyy, on yleensä yksi käyttäjäsäie toiminnassa (käynnistetyn pääohjelman säie). Lisäksi virtuaalikone suorittaa yhtä tai useampaa taustasäiettä hoitamassa taustalla toimivaa roskankeruuta jne. Virtuaalikone suorittaa säikeitä, kunnes ohjelma lopetetaan kutsumalla hyväksytysti Runtime-luokan exit-metodia tai kun kaikki käyttäjäsäikeet ovat lopettaneet toimintansa. Javassa uuden säikeen voi luoda kahdella eri tavalla: Kirjoittamalla luokka, joka perii Thread-luokan, o Luokan run-metodi on uudelleenmääriteltävä, Kirjoittamalla luokka, joka toteuttaa Runnable-rajapinnan, o Luokassa on toteutettava run-metodi. Nämä tavat ovat lähes ekvivalentit; tässä käytetään kumpaakin tapaa, yleensä kuitenkin ensimmäistä. Jälkimmäinen tapa on hieman kevyempi ja sallii periytymisen Säikeen luominen Javassa Thread-luokan oliot kontrolloivat säikeitä. Uuden säikeen luominen aloitetaan uuden Thread-olion luomisella; tämän jälkeen säie konfiguroidaan (annetaan sille prioriteetti, nimi jne voidaan tehdä luomisen yhteydessä) ja lopulta säie laitetaan suoritukseen kutsumalla sen startmetodia. Huomaa, että säikeen toiminta kirjoitetaan run-metodiin, mutta ajo aloitetaan startmetodilla, jolloin järjestelmä kutsuu run-metodia. Säiettä suoritetaan, kunnes run-metodista 7

8 palataan, alati toimivan säikeen voi siis tehdä kirjoittamalla run-metodiin ikuisen silmukan. Seuraavassa esimerkissä toimii kaksi säiettä rinnakkain: class DemoThread extends Thread private int delay; private String line; public DemoThread(String name,string tosay,int dtime) super(name); line = tosay; delay = dtime; public void run() while(true) System.out.println(this.getName() + " says: " + line); try Thread.sleep(delay); catch(interruptedexception ie) return; public class EkaTredit public static void main(string [] argv ) DemoThread DT1 = new DemoThread("Eka jouhi","hui!",300); DemoThread DT2 = new DemoThread("Toka jouhi","hai!",600); DT1.start(); DT2.start(); Pääohjelmassa luodaan kaksi säiettä, jotka tulostavat nimensä ja annetun lausahduksen ja vaipuvat uneen annetuksi ajaksi. Suoritettaessa ohjelmaa konsolille tulostuu noin kaksi HUI! :ta yhtä hai! :ta kohti. Sama toiminto saadaan aikaan käyttämällä Runnable-rajapintaa seuraavasti: class DemoRunnable implements Runnable private int delay; private String objname; private String line; public DemoRunnable(String name,string tosay,int dtime) objname = name; line = tosay; delay = dtime; 8

9 public void run() while(true) System.out.println(objName + " says: " + line); try Thread.sleep(delay); catch(interruptedexception ie) return; public class EkaRun public static void main(string [] argv ) DemoRunnable DR1 = new DemoRunnable( "Eka olio","hui!",300); DemoRunnable DR2 = new DemoRunnable( "Toka olio","hai!",600); new Thread(DR1).start(); new Thread(DR2).start(); Huomaa, että koodi on lähes samanlainen kuin ensimmäisessä ohjelmassa, paitsi että pääohjelmassa luodaan uudet säikeet, joissa Runnable-oliot suoritetaan. Säikeet luodaan antamalla niille luomisen yhteydessä parametrina Runnable-olio Säikeen lopettaminen Säikeen lopettaminen on syytä tehdä palaamalla säikeen run-metodista. Tämä vaatii kuitenkin ohjelmoijalta hieman toimia: yleensä käytetään säikeen keskeyttämistä (interrupt) kutsumalla säikeen interrupt()-metodia. Tämä metodi ei suoraan lopeta säikeen toimintaa vaan laittaa säikeen keskeytystilaan, jota voidaan säikeeltä kysyä isinterrupted()-metodilla. Näin vältetään säikeen väkivaltainen katkaiseminen, joka voi johtaa olioiden korruptoitumiseen. Esimerkiksi ison tiedoston avaamisen tai lataamisen peruutus on syytä tehdä mainitulla tavalla. Esimerkki säikeen keskeyttämisestä: //Määritellään säieluokka class Interruptible extends Thread public void run() while(!this.isinterrupted()) // Tee jotain // Lopputoimenpiteet //Pääohjelmassa koodi: Interruptible irthread = new Interruptible(); irthread.start(); // Toimenpiteet // Lopetetaan irthread irthread.interrupt(); 9

10 Säikeen keskeyttäminen ei siis automaattisesti vaikuta toimivan säikeen suoritukseen. Koska nukkuva (sleep) tai odottava (wait) säie ei ole parhaillaan suorituksessa, sitä ei voi suoraan keskeyttää. Tällaisen säikeen keskeyttäminen aiheuttaa siksi poikkeuksen InterruptedException heittämisen. Tämän vuoksi aina, kun säie nukutetaan tai laitetaan se odottamaan, on kyseinen poikkeus otettava kiinni tai heitettävä se eteenpäin Säikeiden prioriteetti ja säieryhmät Jokaisella Javan säikeellä on prioriteetti, joka säätelee säikeen saamaa keskusyksikköaikaa suhteessa muihin säikeisiin. Mikäli kaksi säiettä on yhtä aikaa kilpailemassa keskusyksikköajasta, korkeamman prioriteetin säie voittaa. Saman prioriteetin säikeet saavat keskimäärin saman verran aikaa keskusyksiköltä. Järjestelmästä riippuu mitkä ovat eri prioriteettien säikeiden suhteelliset keskusyksikköajat. Säikeen prioriteettiin voi vaikuttaa ohjelmallisesti ennen säikeen käynnistämistä, mutta säikeen prioriteettia ei voi nostaa sen säieryhmän maksimiprioriteettia korkeammalle. Javan säikeiden prioriteetit ovat kokonaislukuja väliltä Thread.MIN_PRIORITY Thread.MAX_PRIORITY. Ellei säikeelle anneta erikseen prioriteettia, se saa arvon Thread.NORM_PRIORITY. Jokainen Javan säie kuuluu täsmälleen yhteen säieryhmään (ThreadGroup). Kun säie perustetaan, se liitetään perustavan säikeen ryhmään, mikäli erikseen ei toisin mainita. Säieryhmät voivat sisältää toisia säieryhmiä jäseninään. Kun Javan virtuaalikone käynnistyy, perustetaan järjestelmäsäieryhmä, jonka jäseniä kaikki perustettavat säieryhmät ovat. Näin ollen Javasovelluksen säieryhmät muodostavat puurakenteen, jonka juuri on järjestelmäsäieryhmä. Kun sovellus käynnistyy, virtuaalikone perustaa pääsäieryhmän systeemisäieryhmän jäseneksi. Aluksi pääsäieryhmässä on vain pääsäie, joka suorittaa pääohjelmaa. Käyttäjän luomat säikeet lisätään pääsäieryhmään; käyttäjä voi kuitenkin luoda uusia säieryhmiä ja niihin uusia säikeitä halutessaan. Säieryhmillä voi hallita säikeitä paremmin, koska jokaiselta säikeeltä voi kysyä, mihin säieryhmään se kuuluu ja käyttää sitten säieryhmien operaatioita tähän ryhmään. Säieryhmälle voidaan esimerkiksi asettaa prioriteetin maksimiarvo, jolloin minkään ryhmään kuuluvan säikeen prioriteetti ei saa ylittää kyseistä arvoa. Tässä ei kuitenkaan perehdytä tarkemmin säieryhmien hallintaan Säikeen elinkaari Javan säie voi olemassaolonsa aikana olla kuudessa eri tilassa (ks. Uusi (NEW) Säie on luotu, mutta sen start-metodia ei ole kutsuttu, joten se ei voi vielä toimia. Ajettava (RUNNABLE) Säie voi toimia, heti kun se saa keskusyksiköltä aikaa suorittaakseen operaatioitansa. Estetty (BLOCKED) Säikeen toiminta on estetty, koska se odottaa monitorin lukon vapautumista. Odottaa (WAITING) Säie odottaa kunnes toinen säie suorittaa määrätyn toimenpiteen. Odottaa ajastetusti (TIMED_WAITING) Säie odottaa kunnes toinen säie suorittaa määrätyn toimenpiteen tai kun annettu aika on kulunut. 10

11 Lopetettu, kuollut (TERMINATED) Säikeen suoritus on loppunut eli sen run-metodi on päättynyt. Kun uusi säie luodaan, se saadaan ajettavaksi kutsumalla sen start-metodia. Tällöin se menee ajettavaan tilaan. Ajettavat säikeet ovat joko toiminnassa tai jonossa odottamassa keskusyksikköaikaa. Säie pysyy ajettavana, kunnes se menee odottamaan, sen toiminta estetään tai se kuolee. Estetty säie voi jälleen mennä ajettavaan tilaan, kun sen estävä seikka lakkaa vaikuttamasta. Kuollutta säiettä ei sen sijaan voi enää herättää eloon. Tuonnempana käsitellään tarkemmin, miten säie voi joutua yllä mainittuihin tiloihin. Huomautus. Säikeen nukuttaminen ei vapauta lukkoa, mikäli säikeellä on sellainen hallussaan. Näin ollen synkronoitu metodi voi sisältää sleep-lauseen ja silti estää toisten synkronoitujen metodien suorittamisen samanaikaisesti. Synkronointia käsitellään myöhemmin Säikeiden yhdistäminen Koska säikeet käyttävät yhteistä muistialuetta, ne voivat kommunikoida yhteisten muuttujien ja olioiden välityksellä. Usein kuitenkin joudutaan tilanteisiin, joissa (esimerkiksi lukkiutumisen vaaran takia) säikeet joutuvat odottamaan toisten säikeiden suorittamia operaatioita ennen suorituksen jatkamista. Tähän on kaksi perusmekanismia: Säikeiden yhdistymisen odottaminen ja oliopohjainen odottaminen. Käsitellään nyt säikeiden yhdistymisen odottaminen. Thread-luokassa on metodi join(), jonka avulla säie voi odottaa toisen säikeen suorituksen loppumista. Yksinkertainen esimerkki tällaisesta on: class JoinThread extends Thread private int delay; public JoinThread(String name,int dtime) super(name); delay = dtime; public void run() try Thread.sleep(delay); catch(interruptedexception ie) return; System.out.println(this.getName() + " finished "); 11

12 public class JoinTest public static void main(string [] argv ) JoinThread DT1 = new JoinThread("Eka jouhi",4000); JoinThread DT2 = new JoinThread("Toka jouhi",2000); try DT1.start(); DT2.start(); DT1.join(); DT2.join(); catch(interruptedexception ie) ; System.out.println("Program finished"); Tässä pääohjelman säie joutuu odottamaan kunnes kaksi luotua säiettä lopettavat toimintansa. Näin ollen ohjelma tulostaa noin kahden sekunnin kuluttua: Toka jouhi finished ja jälleen tästä kahden sekunnin kuluttua: Eka jouhi finished Program finished Jos pääohjelmasta kommentoidaan join-lauseet pois, niin heti tulostetaan Program finished ja vasta säikeiden päättymisen jälkeen säikeiden lopettamisviestit. Tätä menetelmää voidaan käyttää rinnakkaisessa ohjelmoinnissa esimerkiksi kun ohjelman suoritus hajautetaan useaan säikeeseen ja lopputulosta varten tarvitaan kaikkien säikeiden tulokset. Thread-luokassa on myös metodi yield(), jota kutsuttaessa säie luopuu suoritusvuorostaan ja antaa muiden säikeiden mennä suoritukseen Synkronointi Javassa Ohjelman oikeellisuuden varmistamiseksi säikeiden on yleensä jaksotettava toimintansa niin, että ongelmatapauksia ei ilmene. Tätä sanotaan säkeiden synkronoinniksi (synchronization), joka voi ilmetä kilpailun synkronointina (competition synchronization) ja yhteistoiminnan synkronointina (cooperation synchronization). Kilpailun synkronointia tarvitaan, kun kaksi säiettä yrittää toisistaan riippumatta käyttää jotakin resurssia ja on vaara, että tästä aiheutuu resurssin tilan rikkoutuminen. Kilpailun synkronointi toteutetaan yleensä siten, että säie pyytää joltakin synkronointioliolta resurssin käyttöoikeutta ja vapauttaa resurssin jälleen muiden säikeiden käyttöön lopetettuaan operaationsa. Yhteistoiminnan synkronointia taas tarvitaan, kun jonkin säikeen A operaation suorittaminen riippuu toisen säikeen B toiminnasta, jolloin säie A joutuu odottamaan, kunnes säie B saa suoritettua operaationsa. Synkronoinnin onnistuminen taataan yleensä jollakin rakenteellisella mekanismilla; Javan sisäänrakennettu synkronointimekanismi on ns. monitori. Monitori on olio, joka kapseloi halutut 12

13 toiminnot sisäänsä niin, että niitä pääsee suorittamaan vain monitorin suostumuksella. Vain yksi säie voi kerrallaan suorittaa toimintoja tällöin sanotaan että säikeellä on hallussaan monitorin lukko (lock). Monitorilla on myös (vähintään yksi) odotusjoukko (wait set), johon sijoitetaan toimintoja suorittamaan haluavat säikeet. Kun lukkoa hallussaan pitävä säie luopuu siitä, jokin odotusjoukon säie saa lukon haltuunsa ja oikeuden suorittaa monitorin valvomia toimintoja. Säie luopuu lukosta joko poistumalla monitorista lopettamalla operaation suorituksen tai ilmoittamalla (signal, notify) jollekin odotusjoukon säikeelle. Monitorin yleisimmän määritelmän perusteella monitorilla voi olla useita odotusjoukkoja, joihin odottavat säikeet sijoitetaan ehtomuuttujien (condition variables) perusteella. Tällöin säikeen on odottamaan mennessään ilmoitettava, mistä ehtomuuttujasta odottaminen riippuu, ja ilmoittavan säikeen on kohdistettava ilmoituksensa tiettyyn ehtomuuttujaan. Lisäksi monitoriin sisältyy usein broadcast-tyylinen ilmoittaminen, jossa ilmoitus annetaan kaikille odotusjoukon säikeille. Javassa mikä tahansa olio voi toimia monitorina. Näin ollen monitorit ovat luonnollinen mekanismi Java-kielisessä rinnakkaisohjelmoinnissa ja ovat lähes aina vähintään implisiittisesti esillä. Javan monitoritoteutuksessa ei käytetä ehtomuuttujia; näin ollen oliolla on aina vain yksi odotusjoukko ja siten loogisesti yksi ehtomuuttuja. Ehtomuuttujien käyttö onnistuu kuitenkin Javan kehittyneemmillä, myöhemmin kieleen lisätyillä ominaisuuksilla Kilpailun synkronointi Rinnakkaisten säikeiden käyttö voi siis johtaa moniin ongelmiin, joista yksi on datan turmeltuminen. Olion data voi turmeltua kahden eri säikeen suorittaessa samanaikaisia operaatioita olioon. Oletetaan, että seuraava yksinkertainen luokka mallintaa pankkitiliä: class PankkiTili private double saldo=0; // Konstruktori public PankkiTili(double alkusaldo) if( alkusaldo > 0) saldo = alkusaldo; else saldo = 0; // Saantimetodi - saldon antaminen public double annasaldo() return saldo; /* Metodit - tililtä otto ja tilille pano*/ public boolean otatililta(double otto) boolean ottook; if(otto > 0 && otto <= saldo) saldo = saldo - otto; ottook = true; else ottook = false; return ottook; 13

14 public boolean panetilille(double pano) boolean panook; if(pano > 0) saldo = saldo + pano; panook = true; else panook = false; return panook; Oletetaan, että kaksi säiettä käyttää samaa PankkiTili-oliota yhtä aikaa; toisesta ollaan tekemässä panoa ja toisesta ottoa. Olkoon saldo ennen kumpaakin tapahtumaa 1000; tililtä otetaan 500 ja tillille pannaan 600. Koska säikeet ovat toisistaan riippumattomia, huonolla onnella ne saattavat toimia seuraavasti: Ottoa suorittava säie lukee saldon Panoa suorittava säie lukee saldon Panoa suorittava säie kirjoittaa saldo = Ottoa suorittava säie kirjoittaa saldo = 500 Näin tilin saldoksi jää 500, vaikka pitäisi jäädä Hyvällä onnella tietysti voisi käydä niinkin, että otto jäisi huomiotta. Tämä ei kuitenkaan ole ohjelmoinnin kannalta toivottava tilanne ja se voidaankin ratkaista kilpailun synkronoinnilla. Koska kaikki Javan oliot voivat toimia monitoreina, jokaisella oliolla Javassa on lukko (lock). Lukko estää suorittamasta useita synkronoituja metodeja yhtä aikaa. Kun säie kutsuu olion synkronoitua metodia, se ottaa haltuunsa olion lukon; tällöin mitkään muut säikeet eivät voi kutsua olion mitään synkronoitua metodia, vaan niiden toiminta estetään, kunnes ensimmäinen säie luopuu lukosta, ts. ensiksi kutsutusta synkronoidusta metodista palataan tai säie luopuu lukosta metodia suorittaessaan. Metodista palaaminen voi tapahtua joko normaalisti tai virheen tai poikkeuksen seurauksena. Tavallisia, ei-synkronoituja metodeja sen sijaan voidaan kutsua samanaikaisesti toisistakin säikeistä. Metodi voidaan määritellä synkronoiduksi lisäämällä sen esittelyyn sana synchronized. Tästä komennosta on toinenkin muoto synchronized(lukkoolio), jolla voidaan lukita jokin muu olio (tässä tapauksessa lukkoolio) kuin metodin omistava olio, näin voidaan lukita myös koodilohko eikä tarvitse rajoittua koko metodiin. 14

15 Seuraavat määritelmät ovat ekvivalentit: synchronized void f() // Metodin runko void f() synchronized(this) // Metodin runko Yleisin käyttötapa on luonnollisesti lukita this, mutta muitakin lukitusmekanismeja joutuu joskus soveltamaan. Näitä menetelmiä käsitellään jatkossa tarkemmin. Pankkitililuokka saataisiin toimimaan rinnakkaisena seuraavasti: class RinnakkaisPankkiTili private double saldo=0; public RinnakkaisPankkiTili (double alkusaldo) if( alkusaldo > 0) saldo = alkusaldo; else saldo = 0; synchronized public double annasaldo() return saldo; synchronized public boolean otatililta(double otto) boolean ottook; if(otto > 0 && otto <= saldo) saldo = saldo - otto; ottook = true; else ottook = false; return ottook; synchronized public boolean panetilille(double pano) boolean panook; if(pano > 0) saldo = saldo + pano; panook = true; else panook = false; return panook; 15

16 Nyt yllä esiintynyt datan turmeltuminen ei ole mahdollinen, sillä säie, joka kutsuu otatililtametodia saa haltuunsa olion lukon ja jos toinen säie kutsuu panetilille-metodia, se joutuu estetyksi, kunnes ensimmäinen säie suorittaa oton valmiiksi. Kannattaa huomata, että myös metodi annasaldo on määritelty synkronoiduksi, jotta sitä ei voi kutsua samanaikaisesti tilin saldoa muuttavien metodien kanssa. Luokan konstruktoria ei voi määritellä synkronoiduksi, eikä siihen ole syytäkään, sillä olio luodaan vain yhdessä säikeessä kerran. Mikäli jostain ohjelmointiteknisestä syystä jouduttaisiin käyttämään jo olemassa olevaa luokkaa, jota ei ole kirjoitettu rinnakkaisuutta silmälläpitäen, eikä koodia voisi kopioida sellaisenaan, voitaisiin käyttää hyväksi periytymistä. Kirjoitetaan PankkiTili-luokasta periytyvä luokka, jossa on täsmälleen samat metodit kuin alkuperäisessä luokassa, mutta synkronoituina ja kutsutaan emoluokan metodeja super-viitteellä: class SynkronoituPankkiTili extends PankkiTili public SynkronoituPankkiTili (double alkusaldo) super(alkusaldo); synchronized public double annasaldo() return super.annasaldo(); synchronized public boolean otatililta(double otto) return super.otatililta(otto); synchronized public boolean panetilille(double pano) return super.panetilille(pano); Nyt SynkronoituPankkiTili toimii muuten täsmälleen kuten alkuperäinen PankkiTili, mutta metodit on synkronoitu ja luokkaa voidaan käyttää monisäikeisessä ohjelmassa. Huomautus. Kun luokka peritään, lapsiluokassa uudelleen määriteltävät synkronoidut metodit eivät automaattisesti ole synkronoituja, vaan ne on tarvittaessa määriteltävä sellaisiksi. Kun lapsiluokasta kutsutaan kantaluokan synkronoitua metodia super-viitteen avulla, olio lukkiutuu vaikka lapsiluokan metodia ei olisikaan määritelty synkronoiduksi, koska kantaluokan metodi on synkronoitu. Koska yllä käsitelty lukko on oliokohtainen, oliokohtaisten synkronoitujen metodien kutsuminen ei vaikuta luokkakohtaisiin static-metodeihin. Javassa on lisäksi toteutettu luokkakohtainen lukko, joten myös static-metodit voidaan määritellä synkronoiduiksi. Luokkakohtainen ja oliokohtainen lukko ovat toisistaan riippumattomat, joten kun luokkakohtainen synkronoitu metodi on ajossa, voidaan kutsua oliokohtaista synkronoitua metodia ja päinvastoin. Luokkakohtaista lukkoa käyttäen myös RinnakkaisPankkiTili-luokan olion luominen saataisiin synkronoitua, mikäli se olisi tarpeellista. Nyt voitaisiin nimittäin muuttaa luokan konstruktori private-tyyppiseksi, jolloin olion muodostaminen olisi mahdollista ainoastaan luokan sisältä. Tällöin luokkaan tarvitaan staattinen metodi, joka huolehtii instanssin luomisesta ja tämä voi olla synkronoitu. Näin ollen luokan koodi muuttuisi muotoon: 16

17 class RinnakkaisPankkiTili private double saldo=0; synchronized static public RinnakkaisPankkiTili luoolio(double alkusaldo) return new RinnakkaisPankkiTili(alkuSaldo); private RinnakkaisPankkiTili (double alkusaldo) // jne Tällöin tiliä käyttävä ohjelma ei voi luoda pankkitilioliota RinnakkaisPankkiTili rpt = new RinnakkaisPankkiTili(123.23); kuten ennen vaan on luotava se seuraavasti: RinnakkaisPankkiTili rpt = RinnakkaisPankkiTili.luoOlio(123.23); Huomautus 2. Synkronointi on resursseja kuluttava toimenpide, joten kaikkia luokkia ja niiden metodeja ei kannata kirjoittaa synkronoiduiksi, vaan huolellisella suunnittelulla pitää synkronoitujen metodien määrä mahdollisimman pienenä mutta kuitenkin riittävänä Yhteistoiminnan synkronointi Jokaisella oliolla on monitorina lukon lisäksi odotusjoukko (wait set), johon voidaan vaikuttaa vain Object-luokan metodeilla wait(), notify() ja notifyall() sekä Thread-luokan metodilla interrupt(). Olion odotusjoukko koostuu niistä säikeistä, joiden toiminta on estetty kutsumalla säikeestä olion wait-metodia. Javan virtuaalikone pitää sisäisesti yllä odotusjoukkoa kullekin oliolle eikä päästä säikeitä suoritukseen ennen kuin odotuksen ilmoitetaan loppuvan tai se loppuu jonkin poikkeustoiminnon seurauksena. Jotta säie voisi kutsua olion wait-metodia, sillä on oltava hallussaan olion lukko. Toisin sanoen, metodia voi koodissa kutsua ainoastaan synkronoidussa metodissa tai synkronoidun lohkon sisältä. Sama pätee notify- ja notifyall-metodeihin. Metodista wait on kolme muotoa: wait() o odottaa, kunnes säie vapautetaan wait(millisecs) o odottaa, kunnes säie vapautetaan tai millisecs millisekuntia on kulunut wait(millisecs,nanosecs) o odottaa, kunnes säie vapautetaan tai millisecs millisekuntia ja nanosecs nanosekuntia on kulunut Kun säie siirtyy odotustilaan, se luonnollisesti myös vapauttaa olion lukon. Paitsi ajastettuna, säie voi vapautua odotuksesta, mikäli: Jokin toinen säie kutsuu olion notify()-metodia. Tällöin jokin olion odotusjoukon säikeistä vapautuu. Valinnan tekee järjestelmä satunnaisesti. Jokin toinen säie kutsuu olion notifyall()-metodia. Tällöin kaikki olion odotusjoukon säikeet vapautuvat Jokin toinen säie keskeyttää (interrupt) odottavan säikeen. Tällöin heitetään poikkeus InterruptedException. 17

18 Kun säie vapautuu, se kilpailee normaaliin tapaan muiden säikeiden kanssa olion synkronoinnissa. Jos säie on keskeytetty, InterruptedException heitetään vasta silloin, kun säikeelle annetaan kontrolli olioon. Esimerkki. Kirjoita ohjelma, jossa omassa säikeessään toimiva tuottajaolio tuottaa kokonaislukuja niin ikään omassa säikeessään toimivalle kuluttajaoliolle. Tuottamiseen kuluu ennalta määrätty aika; samoin kuluttamiseen. Jokainen tuotettu luku on kulutettava täsmälleen kerran. Ratkaisu: Tehtävä voidaan ratkaista niin, että kirjoitetaan luokka, jossa on jäsenmuuttuja tuotetulle kokonaisluvulle ja synkronoidut metodit setvalue(), joka asettaa uuden tuotetun arvon getvalue(), joka palauttaa viimeksi tuotetun luvun Luokan olio toimii monitorina, joka synkronoi lukujen tuottamisen ja kuluttamisen niin, että uutta lukua ei voida tuottaa ennen kuin edellinen on annettu kulutettavaksi eikä myöskään jo kerran kulutettavaksi annettua lukua voida kuluttaa uudelleen. Tämä toteutetaan tutkimalla booleantyyppistä jäsenmuuttujaa joka kertoo, onko tuotettu luku jo kulutettu. Tämän perusteella säie asetetaan odottamaan, ellei operaatiota voida suorittaa. Kun tuottaminen tai kulutettavaksi luovuttaminen on tapahtunut, on odottavalle säikeelle ilmoitettava muutoksesta. Lopullinen ohjelma on // Monitoriolio class ProdConMonitor int myint=0; private boolean valueset = false; synchronized void setvalue(int newval) if(valueset) try this.wait(); catch(interruptedexception ie) myint = newval; System.out.println("Produced " + myint); valueset = true; this.notify(); synchronized int getvalue() if(!valueset) try this.wait(); catch(interruptedexception ie) // Handle Excp valueset = false; System.out.println("Consuming " + myint); this.notify(); return myint; 18

19 // Tuottaja class IntProducer extends Thread ProdConMonitor mymonitor; public IntProducer(ProdConMonitor pcm) mymonitor = pcm; public void run() int i = 1; while(true) // Produce new Int try Thread.sleep(10); catch(interruptedexception ie) break; mymonitor.setvalue(i); i++; // Kuluttaja class IntConsumer extends Thread ProdConMonitor mymonitor; public IntConsumer(ProdConMonitor pcm) mymonitor = pcm; public void run() while(true) // Consume next int mymonitor.getvalue(); try Thread.sleep(100); catch(interruptedexception ie) break; 19

20 // Pääohjelma public class NotificationEx public static void main(string[] args) ProdConMonitor pcm = new ProdConMonitor(); IntProducer ipprod = new IntProducer(pcm); IntConsumer iccon = new IntConsumer(pcm); iccon.start(); ipprod.start(); 3. Rinnakkaisen ohjelmoinnin malleja Seuraavaksi esitetään kaksi yleiskäyttöistä rinnakkaisen ohjelmoinnin mallia: Tuottajakuluttajamalli ja Lukija-kirjoittajamalli. Nämä kumpikin esiintyvät rinnakkaisissa ohjelmissa eri muodoissa Tuottaja-kuluttajamalli Useat rinnakkaisen ohjelmoinnin suunnitteluongelmat voidaan ratkaista käyttämällä tuottaja kuluttajamallia. Mallissa on kahdentyyppisiä säikeitä (tai prosesseja): Tuottajat o Luovat uusia olioita (dataa), jotka lähetetään kuluttajille. Kuluttajat o Käsittelevät tuottajien luomia olioita. Malli on yleinen ja soveltuu moniin erilaisiin tapauksiin, kuluttaja voi olla esimerkiksi yksittäinen tulostusprosessi, joka käsittelee useista lähteistä saapuvaa tulostettavaa dataa. Tällöin yhtä kuluttajaa kohti on useita tuottajia. Joskus tarvitaan useita kuluttajia, jos esimerkiksi tuottajat tuottavat monen tyyppisiä olioita, jotka kaikki vaativat omanlaisensa kuluttajan käsittelemään niitä. Yksinkertaisimmillaan mallin toteutus on yhden tuottajan ja yhden kuluttajan tapauksessa, kun operaatio etenee synkronoidusti, ts. tuottaja tuottaa olion, kuluttaja käsittelee sen minkä jälkeen tuottaja tuottaa uuden olion jne. Yhteistoiminnan synkronointia käsittelevässä osassa tehtiin esimerkkinä tällainen toteutus, joka on kuitenkin moniin tapauksiin liian joustamaton; usein on tarpeellista antaa tuottajan luoda useita olioita ja kuluttajan kuluttaa niitä omaan tahtiinsa. Tällöin tarvitaan puskuria sisältämään tuotetut oliot. Mikäli puskuri on ääretön, ei tarvitse huolehtia sen täyttymisestä. Käytännössä ääretön puskuri voidaan toteuttaa linkitetyllä listalla. Javan tapahtumankäsittely käyttää ääretöntä puskuria, ns. tapahtumajonoa (event queue). Kun ohjelmassa tuotetaan jokin UI-tapahtuma, siitä luodaan olio, joka menee tapahtumajonoon. Tapahtumanvälittäjä (event dispatcher) hakee tapahtumaoliot jonosta yksitellen ja välittää ne edelleen asianmukaiseen paikkaan käsiteltäviksi. Monesti on tarkoituksenmukaista käyttää kuitenkin käyttää äärellistä puskuria, jolloin se voidaan toteuttaa taulukkona. Etuna on kirjoituksen ja lukemisen nopeus ja yksinkertaisuus, mutta toisaalta on pidettävä huoli siitä, että täyteen puskuriin ei enää kirjoiteta. Useimmiten puskuri toteutetaan (synkronoituna) syklisenä puskurina (rengaspuskuri, circular buffer), jolloin puskurin viimeisen 20

21 paikan jälkeen kirjoitettaan aina ensimmäiseen jne. Tässäkin tapauksessa on luonnollisesti pidettävä huoli siitä, että täyteen puskuriin ei enää kirjoiteta, koska silloin tietoa häviää. Kirjoitetaan Java-luokka CircularBuffer, jossa on toteutettu metodit put ja take puskuriin lukemista ja kirjoittamista varten. Metodit on kirjoitettava synkronoiduiksi, jotta puskuria voidaan käyttää useammasta säikeestä. Tällöin luokkaa voidaan käyttää Tuottaja-kuluttajamallin toteutuksessa; tuottajia ja kuluttajia voi olla useita yhtä puskuria kohti. public class CircularBuffer protected final Object[] buffer; protected int putptr = 0; protected int takeptr = 0; protected int queueditems = 0; public CircularBuffer(int size) throws IllegalArgumentException // Check first that size is OK if( size <= 0) throw new IllegalArgumentException(); buffer = new Object[size]; public int getcapacity() return buffer.length; public synchronized int getcurrentsize() return queueditems; public synchronized void put(object obj) throws InterruptedException // Wait while buffer is full while(queueditems == buffer.length) wait(); // Put object in buffer buffer[putptr] = obj; // Increase putptr cyclically and increase current size putptr = (putptr +1) % buffer.length; queueditems++; // Signal if put to empty buffer if(queueditems == 1) notifyall(); 21

22 public synchronized Object take() throws InterruptedException // Wait while buffer is empty while(queueditems == 0) wait(); Object retobj = buffer[takeptr]; // Increase takeptr cyclically and decrease current size takeptr = (takeptr +1) % buffer.length; queueditems--; // Signal if taken from full buffer if(queueditems == (buffer.length-1) ) notifyall(); return retobj; Huomaa kuitenkin, että mikäli tuottajia ja kuluttajia on suuri joukko, notifyall()-metodia käyttävä toteutus tulee raskaaksi. Tällaisessa tapauksessa voidaan joutua tehokkuussyistä suunnittelemaan erilainen, esimerkiksi ns. kohdistettua ilmoittamista käyttävä toteutus. Nyt voidaan kirjoittaa Producer- ja Consumer-luokat jotka käyttävät hyväkseen ylläolevaa puskuria. Luokat kannattaa kirjoittaa abstrakteiksi, koska yleensä tuottaminen ja kuluttaminen ovat tapauskohtaisia operaatioita ja näin ollen metodit produce ja consume tulee määritellä uudelleen toteutuksessa. abstract class Producer private CircularBuffer cbbuffer; public Producer(CircularBuffer cb) cbbuffer = cb; abstract Object produce(); public void putobject(object obj) throws InterruptedException cbbuffer.put(obj); abstract class Consumer private CircularBuffer cbbuffer; public Consumer(CircularBuffer cb) cbbuffer = cb; abstract void consume(object obj); public Object takeobject() throws InterruptedException return cbbuffer.take(); public int getnumstored() return cbbuffer.getcurrentsize(); 22

23 Esimerkki. Nukkuvan parturin ongelma. Ongelma on peräisin Dijkstran semaforien käyttöä koskevasta artikkelista ([Dij2]). Parturilla on ateljeessaan leikkuutuolinsa lisäksi neljä tuolia odottaville asiakkaille. Kun parturi on leikannut asiakkaan hiukset, hän ottaa käsittelyyn ensimmäiseksi odottamaan tulleen asiakkaan. Mikäli asiakkaita ei ole, parturi nukahtaa leikkuutuoliinsa. Jos kaikki odotussalin tuolit ovat täynnä, sisään pyrkivä asiakas kääntyy pois ja tulee myöhemmin uudelleen. Kirjoita ohjelma, joka simuloi tätä tilannetta. Edellä konstruoituja luokkia käyttäen nukkuvan parturin ongelma voitaisiin ratkaista seuraavalla koodilla. Ohjelmaan on toteutettu graafinen käyttöliittymä ilmoittamaan tapahtumista. Tähän liittyvä koodi on kommentoitu pois. import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; class Customer private int custno; public Customer(int no) custno = no; public String tostring() return "Customer number " + custno; class Barber extends Consumer implements Runnable private String name = "Monitor Barber"; private int maxcuttime; private JTextArea noteboard; private Random rndgen; public Barber(CircularBuffer cb,int maxtime, JTextArea ta) super(cb); maxcuttime = maxtime; noteboard = ta; rndgen = new Random(); protected void consume(object obj) Customer c = (Customer)obj; // Ilmoita leikkauksen alkavan try Thread.sleep( Math.abs(rndGen.nextInt(1000 * maxcuttime)) ); catch(interruptedexception ie) Thread.currentThread().interrupt(); // Ilmoita leikkauksen loppuneen 23

24 public void run() Object obj; while(true) try if( getnumstored() == 0 ) // Ilmoita parturin nukahtaneen obj = takeobject(); consume(obj); catch(interruptedexception ie) break; class CustomerAppearance extends Producer implements Runnable private int maxappeartime; private JTextArea noteboard; private int CustomerNum = 0; private Random rndgen; public CustomerAppearance(CircularBuffer cb,int maxtime,jtextarea ta) super(cb); maxappeartime = maxtime; noteboard = ta; rndgen = new Random(); protected Object produce() Object obj; try Thread.sleep( Math.abs(rndGen.nextInt(1000 * maxappeartime)) ); catch(interruptedexception ie) ; CustomerNum++; obj = new Customer(CustomerNum); return obj; public void run() Customer c; while(true) try c = (Customer)produce(); putobject(c); 24

25 // Ilmoita asiakkaan saapuneen catch(interruptedexception ie) break; public class BarberShop extends JFrame implements WindowListener,ActionListener CustomerAppearance caqueue = null; Barber thebarber; Thread BarberThread; Thread CustomerThread; JButton startbutton; JTextArea threadnote = null; CircularBuffer chairs = null; public BarberShop() // Luodaan ikkunan käyttöliittymä // Luodaan puskuri ja säikeet try chairs = new CircularBuffer(4); catch(illegalargumentexception iae) System.out.println("Invalid constrution of circular buffer "); iae.printstacktrace(); System.exit(-1); caqueue = new CustomerAppearance(chairs,6,threadNote); thebarber = new Barber(chairs,2,threadNote); BarberThread = new Thread(theBarber); CustomerThread = new Thread(caQueue); public static void main(string [] argv ) // Käynnistetään ohhjelma java.awt.eventqueue.invokelater(new Runnable() public void run() BarberShop bsprog = new BarberShop(); bsprog.setvisible(true); bsprog.addwindowlistener(bsprog); ); // Start client producer bsprog.customerthread.start(); // Parturin käynnistäminen ja keskeyttäminen napista 25

26 public void actionperformed(actionevent ae) if( ae.getsource() == startbutton) if(barberthread.isalive()) BarberThread.interrupt(); else BarberThread.start(); Toteutuksessa luokka CustomerAppearance toimii tuottajana ja perii abstraktin luokan Producer. Luokka Barber taas toimii kuluttajana ja perii abstraktin luokan Consumer. Ne kommunikoivat yhteisen CircularBuffer-olion välityksellä. Tämä syklinen puskuri sisältää neljä paikkaa ja vastaa odotushuoneen tuoleja. Parturi-olio kuluttaa yhden asiakkaan satunnaisessa ajassa jonka yläraja annetaan sekunteina olion konstruktorin yhteydessä (yllä 2 sekuntia). Tämä on toteutettu implementoimalla consume()-metodi. Asiakkaita saapuu satunnaisin väliajoin, väliajan yläraja annetaan CustomerAppearance-olion luomisen yhteydessä (yllä 6 sekuntia), tämän toteutus on luokan produce() -metodissa. Asiakkaita alkaa saapua heti ohjelman käynnistyessä ja parturi voidaan käynnistää painonapista; samasta napista parturin toiminta lopetetaan. Käyttöliittymässä olevaan tekstialueeseen tulostetaan asiakkaan saapuminen, asiakkaan leikkauksen alkaminen ja päättyminen. Samoin parturin nukahtaminen, mikäli asiakkaat loppuvat. Olennaisia lauseita ohjelmassa ovat c = (Customer)produce(); putobject(c); joilla tuotetaan uusi asiakasolio ja syötetään se sykliseen puskuriin, sekä obj = takeobject(); consume(obj); joka lukee puskurista seuraavan asiakasolion. Huomaa, että olio joudutaan tyypittämään consume() -metodissa Customer-tyyppiseksi, koska syklinen puskuri on kirjoitettu yleisesti Object-tyyppisille olioille, jolloin siihen voidaan kirjoittaa mitä tahansa olioita. Koska Java ei tue moniperintää, ja luokkien Barber ja CustomerAppearance on perittävä Consumerja Producer-luokat, saadaan Barber ja CustomerAppearance-oliot toimimaan omissa säikeissään antamalla niiden toteuttaa Runnable-rajapinta. Tällöin niihin voidaan kirjoittaa run-metodi, ja käynnistää se omassa säikeessään, kuten ohjelmassa on tehty. Asiakkaiden tuottaminen tapahtuu nyt määrittelemällä uudelleen Producer-luokan abstrakti metodi produce() ja kuluttaminen määrittelemällä uudelleen Consumer-luokan abstrakti metodi consume(). 26

815338A Ohjelmointikielten periaatteet

815338A Ohjelmointikielten periaatteet 815338A Ohjelmointikielten periaatteet 2015-2016 IX Rinnakkainen ohjelmointi Sisältö 1. Yleistä rinnakkaisuudesta 2. Prosesseista ja säikeistä 3. Rinnakkaisen ohjelman oikeellisuudesta 4. Rinnakkaisuuden

Lisätiedot

812315A Ohjelmiston rakentaminen. Asynkronisuus

812315A Ohjelmiston rakentaminen. Asynkronisuus 812315A Ohjelmiston rakentaminen. Asynkronisuus Ari Vesanen ari.vesanen (at) oulu.fi Yleistä moduulista Tällä kertaa sisältää Java-kielistä monisäieohjelmointia Suoritustapa: Neljästä ohjelmointitehtävästä

Lisätiedot

Concurrency - Rinnakkaisuus. Group: 9 Joni Laine Juho Vähätalo

Concurrency - Rinnakkaisuus. Group: 9 Joni Laine Juho Vähätalo Concurrency - Rinnakkaisuus Group: 9 Joni Laine Juho Vähätalo Sisällysluettelo 1. Johdanto... 3 2. C++ thread... 4 3. Python multiprocessing... 6 4. Java ExecutorService... 8 5. Yhteenveto... 9 6. Lähteet...

Lisätiedot

Projekti 1 Säikeet ja kriittisen vaiheen kontrollointi javalla

Projekti 1 Säikeet ja kriittisen vaiheen kontrollointi javalla Projekti 1 Säikeet ja kriittisen vaiheen kontrollointi javalla Lasse Leino ja Marko Kahilakoski Helsingin Yliopisto Tietojenkäsittelytieteen laitos Rinnakkaisohjelmointi 18. joulukuuta 2006 Sisältö 1 Säikeet

Lisätiedot

Rinnakkaisohjelmointi kurssi. Opintopiiri työskentelyn raportti

Rinnakkaisohjelmointi kurssi. Opintopiiri työskentelyn raportti Rinnakkaisohjelmointi kurssi Opintopiiri työskentelyn raportti Opintopiiri: Heikki Karimo, Jesse Paakkari ja Keijo Karhu Päiväys: 15.12.2006 Ohjelmointitehtävä C i C i : Säikeet ja kriittisen vaiheen kontrollointi

Lisätiedot

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä Ohjelmoinnin peruskurssien laaja oppimäärä Luento 19: Rinnakkaisuus Riku Saikkonen (merkityt ei-laajan kurssin kalvot: Otto Seppälä) 24. 3. 2011 Sisältö 1 Säikeet 2 Lukot 3 Monitorit 4 Muuta säikeisiin

Lisätiedot

Rinnakkaisohjelmointi, Syksy 2006

Rinnakkaisohjelmointi, Syksy 2006 Rinnakkaisohjelmointi, Syksy 2006 17.12.2006 Opintopiiri WTF Mika Holmström Paula Kemppi Janne Piippo Lasse Lukkari Javan semaforit 1. Menetelmän käyttötarkoitus ja sovellusalue Semaforin idea kehitettiin

Lisätiedot

Luento 6. T Ohjelmoinnin jatkokurssi T1 & T Ohjelmoinnin jatkokurssi L1. Luennoitsija: Otto Seppälä

Luento 6. T Ohjelmoinnin jatkokurssi T1 & T Ohjelmoinnin jatkokurssi L1. Luennoitsija: Otto Seppälä Luento 6 T-106.1240 Ohjelmoinnin jatkokurssi T1 & T-106.1243 Ohjelmoinnin jatkokurssi L1 Luennoitsija: Otto Seppälä Kurssin WWW: http://www.cs.hut.fi/opinnot/t-106.1240/s2007 Oma Grafiikka Swing-käyttöliittymässä

Lisätiedot

Monitorit -projekti Rinnakkaisohjelmointi

Monitorit -projekti Rinnakkaisohjelmointi Monitorit -projekti Rinnakkaisohjelmointi 13.12.2006 Jaakko Louhio, Lari Sorvo Projektin tuloksia, kertaustehtäviä ja koodeja saa käyttää opetukseen yliopistolla vapaasti omalla vastuulla. 3. MONITORIT

Lisätiedot

Olio-ohjelmointi Javalla

Olio-ohjelmointi Javalla 1 Olio-ohjelmointi Javalla Olio-ohjelmointi Luokka Attribuutit Konstruktori Olion luominen Metodit Olion kopiointi Staattinen attribuutti ja metodi Yksinkertainen ohjelmaluokka Ohjelmaluokka 1 Olio-ohjelmointi

Lisätiedot

Jaana Diakite Projekti 1 JAVA-Monitorit 1(13) Rinnakkaisohjelmointi Anu Uusitalo

Jaana Diakite Projekti 1 JAVA-Monitorit 1(13) Rinnakkaisohjelmointi Anu Uusitalo Jaana Diakite Projekti 1 JAVA-Monitorit 1(13) JAVA MONITORIT Monitorien käyttötarkoitus ja sovellusalue Monitorit ovat Java ohjelmointikielen sisäänrakennettu mekanismi säikeiden rinnakkaisuuden hallintaan.

Lisätiedot

Liite 1. Projektin tulokset (Semaforit Javassa) Jukka Hyvärinen Aleksanteri Aaltonen

Liite 1. Projektin tulokset (Semaforit Javassa) Jukka Hyvärinen Aleksanteri Aaltonen Helsingin Yliopisto, tietojenkäsittelytieteen laitos Rinnakkaisohjelmointi (syksy 2006) Liite 1. Projektin tulokset (Semaforit Javassa) Jukka Hyvärinen Aleksanteri Aaltonen a. Käyttötarkoitus ja sovellusalue

Lisätiedot

Rinnakkainen ohjelmointi

Rinnakkainen ohjelmointi Rinnakkainen ohjelmointi Tässä kurssin viimeisessä osassa tutustutaan rinnakkaiseen ohjelmointiin. Aluksi käsitellään rinnakkaisen ohjelmoinnin käsitteitä ja rinnakkaisuuden hallintamekanismeja yleisesti.

Lisätiedot

Rinnakkaisuus. parallel tietokoneissa rinnakkaisia laskentayksiköitä concurrent asioita tapahtuu yhtaikaa. TTY Ohjelmistotekniikka

Rinnakkaisuus. parallel tietokoneissa rinnakkaisia laskentayksiköitä concurrent asioita tapahtuu yhtaikaa. TTY Ohjelmistotekniikka Rinnakkaisuus parallel tietokoneissa rinnakkaisia laskentayksiköitä concurrent asioita tapahtuu yhtaikaa Rinnakkaisuuden etuja: laskennan nopeutuminen (sarjoittuvat operaatiojonot) ilmaisuvoima (ongelman

Lisätiedot

4. Luento: Prosessit ja säikeets. Tommi Mikkonen, tommi.mikkonen@tut.fi

4. Luento: Prosessit ja säikeets. Tommi Mikkonen, tommi.mikkonen@tut.fi 4. Luento: Prosessit ja säikeets Tommi Mikkonen, tommi.mikkonen@tut.fi Agenda Prosessi Säikeet Keskeytykset Keskeytyskäsittely Käyttöjärjestelmäkutsut Prosessielementti Prosessin hallinta Suunnittelunäkökohtia

Lisätiedot

Ohjelmassa henkilön etunimi ja sukunimi luetaan kahteen muuttujaan seuraavasti:

Ohjelmassa henkilön etunimi ja sukunimi luetaan kahteen muuttujaan seuraavasti: 1 (7) Tiedon lukeminen näppäimistöltä Scanner-luokan avulla Miten ohjelma saa käyttöönsä käyttäjän kirjoittamaa tekstiä? Järjestelmässä on olemassa ns. syöttöpuskuri näppäimistöä varten. Syöttöpuskuri

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 2.3.2009 T-106.1208 Ohjelmoinnin perusteet Y 2.3.2009 1 / 28 Puhelinluettelo, koodi def lue_puhelinnumerot(): print "Anna lisattavat nimet ja numerot." print

Lisätiedot

Käyttöjärjestelmät: poissulkeminen ja synkronointi

Käyttöjärjestelmät: poissulkeminen ja synkronointi Käyttöjärjestelmät: poissulkeminen ja synkronointi Teemu Saarelainen Tietotekniikka teemu.saarelainen@kyamk.fi Lähteet Stallings, W. Operating Systems Haikala, Järvinen, Käyttöjärjestelmät Eri Web-lähteet

Lisätiedot

8. Näppäimistöltä lukeminen 8.1

8. Näppäimistöltä lukeminen 8.1 8. Näppäimistöltä lukeminen 8.1 Sisällys Arvojen lukeminen näppäimistöltä Java-kielessä. In-luokka. In-luokka, käännös ja tulkinta Scanner-luokka. 8.2 Yleistä Näppäimistöltä annettujen arvojen (syötteiden)

Lisätiedot

Sisällys. 12. Näppäimistöltä lukeminen. Yleistä. Yleistä 12.1 12.2 12.3 12.4

Sisällys. 12. Näppäimistöltä lukeminen. Yleistä. Yleistä 12.1 12.2 12.3 12.4 Sisällys 12. Näppäimistöltä lukeminen Arvojen lukeminen näppäimistöltä yleisesti. Arvojen lukeminen näppäimistöltä Java-kielessä.. Luetun arvon tarkistaminen. Tietovirrat ja ohjausmerkit. Scanner-luokka.

Lisätiedot

RINNAKKAINEN OHJELMOINTI A,

RINNAKKAINEN OHJELMOINTI A, RINNAKKAINEN OHJELMOINTI 815301A, 18.6.2005 1. Vastaa lyhyesti (2p kustakin): a) Mitkä ovat rinnakkaisen ohjelman oikeellisuuskriteerit? b) Mitä tarkoittaa laiska säikeen luominen? c) Mitä ovat kohtaaminen

Lisätiedot

Graafisen käyttöliittymän ohjelmointi Syksy 2013

Graafisen käyttöliittymän ohjelmointi Syksy 2013 TIE-11300 Tietotekniikan vaihtuva-alainen kurssi Graafisen käyttöliittymän ohjelmointi Syksy 2013 Luento 10 Rinnakkaisuus käyttöliittymäohjelmoinnissa Juha-Matti Vanhatupa Rinnakkaisuus ja käyttöliittymäohjelmointi

Lisätiedot

5. Luento: Rinnakkaisuus ja reaaliaika. Tommi Mikkonen, tommi.mikkonen@tut.fi

5. Luento: Rinnakkaisuus ja reaaliaika. Tommi Mikkonen, tommi.mikkonen@tut.fi 5. Luento: Rinnakkaisuus ja reaaliaika Tommi Mikkonen, tommi.mikkonen@tut.fi Agenda Perusongelmat Jako prosesseihin Reaaliaika Rinnakkaisuus Rinnakkaisuus tarkoittaa tässä yhteydessä useamman kuin yhden

Lisätiedot

812341A Olio-ohjelmointi Peruskäsitteet jatkoa

812341A Olio-ohjelmointi Peruskäsitteet jatkoa 812341A Olio-ohjelmointi 2106 Peruskäsitteet jatkoa Luokkakohtaiset piirteet n Yhteisiä kaikille saman luokan olioille n Liittyvät luokkaan, eivät yksittäiseen olioon n Kaikki ko. luokan oliot voivat käyttää

Lisätiedot

8. Näppäimistöltä lukeminen 8.1

8. Näppäimistöltä lukeminen 8.1 8. Näppäimistöltä lukeminen 8.1 Sisällys Arvojen lukeminen näppäimistöltä Java-kielessä. In-luokka. In-luokka, käännös ja tulkinta Scanner-luokka. 8.2 Yleistä Näppäimistöltä annettujen arvojen (syötteiden)

Lisätiedot

Ohjelmointitaito (ict1td002, 12 op) Kevät 2008. 1. Java-ohjelmoinnin alkeita. Tietokoneohjelma. Raine Kauppinen raine.kauppinen@haaga-helia.

Ohjelmointitaito (ict1td002, 12 op) Kevät 2008. 1. Java-ohjelmoinnin alkeita. Tietokoneohjelma. Raine Kauppinen raine.kauppinen@haaga-helia. Ohjelmointitaito (ict1td002, 12 op) Kevät 2008 Raine Kauppinen raine.kauppinen@haaga-helia.fi 1. Java-ohjelmoinnin alkeita Tietokoneohjelma Java-kieli ja Eclipse-ympäristö Java-ohjelma ja ohjelmaluokka

Lisätiedot

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä Ohjelmoinnin peruskurssien laaja oppimäärä Luento 11: Rinnakkaisuus Riku Saikkonen (osa kalvoista on suoraan ei-laajan kurssin luennoista) 25. 4. 2012 Sisältö 1 Rinnakkaisuusmalleja: säie ja prosessi 2

Lisätiedot

Harjoitus 7. 1. Olkoon olemassa luokat Lintu ja Pelikaani seuraavasti:

Harjoitus 7. 1. Olkoon olemassa luokat Lintu ja Pelikaani seuraavasti: Harjoitus 7 1. Olkoon olemassa luokat Lintu ja Pelikaani seuraavasti: class Lintu //Kentät private int _siivenpituus; protected double _aivojenkoko; private bool _osaakolentaa; //Ominaisuudet public int

Lisätiedot

14. Poikkeukset 14.1

14. Poikkeukset 14.1 14. Poikkeukset 14.1 Sisällys Johdanto. Tarkistettavat ja tarkistamattomat poikkeukset. Poikkeusten tunnistaminen ja sieppaaminen try-catchlauseella. Mitä tehdä siepatulla poikkeuksella? Poikkeusten heittäminen.

Lisätiedot

JAVA on ohjelmointikieli, mikä on kieliopiltaan hyvin samankaltainen, jopa identtinen mm. C++

JAVA on ohjelmointikieli, mikä on kieliopiltaan hyvin samankaltainen, jopa identtinen mm. C++ JAVA alkeet JAVA on ohjelmointikieli, mikä on kieliopiltaan hyvin samankaltainen, jopa identtinen mm. C++ ja Javascriptin kanssa. Huom! JAVA ja JavaScript eivät silti ole sama asia, eivätkä edes sukulaiskieliä.

Lisätiedot

Ohjelmointi 2 / 2010 Välikoe / 26.3

Ohjelmointi 2 / 2010 Välikoe / 26.3 Ohjelmointi 2 / 2010 Välikoe / 26.3 Välikoe / 26.3 Vastaa neljään (4) tehtävään ja halutessa bonustehtäviin B1 ja/tai B2, (tuovat lisäpisteitä). Bonustehtävät saa tehdä vaikkei olisi tehnyt siihen tehtävään

Lisätiedot

9. Periytyminen Javassa 9.1

9. Periytyminen Javassa 9.1 9. Periytyminen Javassa 9.1 Sisällys Periytymismekanismi Java-kielessä. Piirteiden näkyvyys periytymisessä. Ilmentymämetodien korvaaminen. Luokkametodien peittäminen. Super-attribuutti. Override-annotaatio.

Lisätiedot

11. Javan toistorakenteet 11.1

11. Javan toistorakenteet 11.1 11. Javan toistorakenteet 11.1 Sisällys Laskuri- ja lippumuuttujat. Sisäkkäiset silmukat. Tyypillisiä ohjelmointivirheitä: Silmukan rajat asetettu kierroksen verran väärin. Ikuinen silmukka. Silmukoinnin

Lisätiedot

Metodit. Metodien määrittely. Metodin parametrit ja paluuarvo. Metodien suorittaminen eli kutsuminen. Metodien kuormittaminen

Metodit. Metodien määrittely. Metodin parametrit ja paluuarvo. Metodien suorittaminen eli kutsuminen. Metodien kuormittaminen Metodit Metodien määrittely Metodin parametrit ja paluuarvo Metodien suorittaminen eli kutsuminen Metodien kuormittaminen 1 Mikä on metodi? Metodi on luokan sisällä oleva yhteenkuuluvien toimintojen kokonaisuus

Lisätiedot

Sisällys. 14. Poikkeukset. Johdanto. Johdanto

Sisällys. 14. Poikkeukset. Johdanto. Johdanto Sisällys 14. Poikkeukset Johdanto. Tarkistettavat ja tarkistamattomat poikkeukset. Poikkeusten tunnistaminen ja sieppaaminen try-catchlauseella. Mitä tehdä siepatulla poikkeuksella? Poikkeusten heittäminen.

Lisätiedot

Sisällys. 14. Poikkeukset. Johdanto. Johdanto

Sisällys. 14. Poikkeukset. Johdanto. Johdanto Sisällys 14. Poikkeukset Johdanto. Tarkistettavat ja tarkistamattomat poikkeukset. Miten varautua poikkeukseen metodissa? Poikkeusten tunnistaminen ja sieppaaminen try-catchlauseella. Mitä tehdä siepatulla

Lisätiedot

Java-kielen perusteet

Java-kielen perusteet Java-kielen perusteet Tunnus, varattu sana, kommentti Muuttuja, alkeistietotyyppi, merkkijono, literaalivakio, nimetty vakio Tiedon merkkipohjainen tulostaminen 1 Tunnus Java tunnus Java-kirjain Java-numero

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 2.3.2011 T-106.1208 Ohjelmoinnin perusteet Y 2.3.2011 1 / 39 Kertausta: tiedoston avaaminen Kun ohjelma haluaa lukea tai kirjoittaa tekstitiedostoon, on ohjelmalle

Lisätiedot

14. Poikkeukset 14.1

14. Poikkeukset 14.1 14. Poikkeukset 14.1 Sisällys Johdanto. Tarkistettavat ja tarkistamattomat poikkeukset. Miten varautua poikkeukseen metodissa? Poikkeusten tunnistaminen ja sieppaaminen try-catchlauseella. Mitä tehdä siepatulla

Lisätiedot

Javan semaforit. Joel Rybicki, Aleksi Nur mi, Jara Uitto. Helsingin yliopisto

Javan semaforit. Joel Rybicki, Aleksi Nur mi, Jara Uitto. Helsingin yliopisto Javan semaforit Joel Rybicki, Aleksi Nur mi, Jara Uitto 16.12.2007 Helsingin yliopisto Tietojenkäsittelytieteen laitos Tätä ohjetta saa käyttää ja jatkokehittää opetustarkoituksiin. Javan semaforitoteutus

Lisätiedot

12. Näppäimistöltä lukeminen 12.1

12. Näppäimistöltä lukeminen 12.1 12. Näppäimistöltä lukeminen 12.1 Sisällys Arvojen lukeminen näppäimistöltä yleisesti. Arvojen lukeminen näppäimistöltä Java-kielessä. In-luokka. Luetun arvon tarkistaminen. Tietovirrat ja ohjausmerkit.

Lisätiedot

Ohjelmoinnin jatkokurssi, kurssikoe 28.4.2014

Ohjelmoinnin jatkokurssi, kurssikoe 28.4.2014 Ohjelmoinnin jatkokurssi, kurssikoe 28.4.2014 Kirjoita jokaiseen palauttamaasi konseptiin kurssin nimi, kokeen päivämäärä, oma nimi ja opiskelijanumero. Vastaa kaikkiin tehtäviin omille konsepteilleen.

Lisätiedot

JAVA-PERUSTEET. JAVA-OHJELMOINTI 3op A274615 JAVAN PERUSTEET LYHYT KERTAUS JAVAN OMINAISUUKSISTA JAVAN OMINAISUUKSIA. Java vs. C++?

JAVA-PERUSTEET. JAVA-OHJELMOINTI 3op A274615 JAVAN PERUSTEET LYHYT KERTAUS JAVAN OMINAISUUKSISTA JAVAN OMINAISUUKSIA. Java vs. C++? JAVA-OHJELMOINTI 3op A274615 JAVAN PERUSTEET LYHYT KERTAUS Teemu Saarelainen teemu.saarelainen@kyamk.fi Lähteet: http://java.sun.com/docs/books/tutorial/index.html Vesterholm, Kyppö: Java-ohjelmointi,

Lisätiedot

Mikä yhteyssuhde on?

Mikä yhteyssuhde on? 1 Yhteyssuhde Mikä yhteyssuhde on? Yhteyssuhde Javalla Konstruktorit set-ja get-metodit tostring-metodi Pääohjelma 1 Mikä yhteyssuhde on? Tili - : String - : double * 1 Asiakas - hetu: String - : String

Lisätiedot

2 Konekieli, aliohjelmat, keskeytykset

2 Konekieli, aliohjelmat, keskeytykset ITK145 Käyttöjärjestelmät, kesä 2005 Tenttitärppejä Tässä on lueteltu suurin piirtein kaikki vuosina 2003-2005 kurssin tenteissä kysytyt kysymykset, ja mukana on myös muutama uusi. Jokaisessa kysymyksessä

Lisätiedot

12. Javan toistorakenteet 12.1

12. Javan toistorakenteet 12.1 12. Javan toistorakenteet 12.1 Sisällys Yleistä toistorakenteista. Laskurimuuttujat. While-, do-while- ja for-lauseet. Laskuri- ja lippumuuttujat. Tyypillisiä ohjelmointivirheitä. Silmukan rajat asetettu

Lisätiedot

Monitorit. Monitori Synkronointimenetelmiä Esimerkkejä. Andrews , Stallings 5.5

Monitorit. Monitori Synkronointimenetelmiä Esimerkkejä. Andrews , Stallings 5.5 Monitorit Monitori Synkronointimenetelmiä Esimerkkejä Andrews 5.1-5.2, Stallings 5.5 Tavoite Minimoi virhemahdollisuuksia poissulkeminen ohjelmoijan vastuulla P():t ja V():t siellä, täällä ja tuolla -

Lisätiedot

Monitorit. Tavoite. Monitori Synkronointimenetelmiä Esimerkkejä. Andrews , Stallings 5.5. Minimoi virhemahdollisuuksia

Monitorit. Tavoite. Monitori Synkronointimenetelmiä Esimerkkejä. Andrews , Stallings 5.5. Minimoi virhemahdollisuuksia Monitorit Monitori Synkronointimenetelmiä Esimerkkejä Andrews 5.1-5.2, Stallings 5.5 Tavoite Minimoi virhemahdollisuuksia poissulkeminen ohjelmoijan vastuulla P():t ja V():t siellä, täällä ja tuolla -

Lisätiedot

Lohkot. if (ehto1) { if (ehto2) { lause 1;... lause n; } } else { lause 1;... lause m; } 16.3

Lohkot. if (ehto1) { if (ehto2) { lause 1;... lause n; } } else { lause 1;... lause m; } 16.3 16. Lohkot 16.1 Sisällys Tutustutaan lohkoihin. Muuttujien ja vakioiden näkyvyys sekä elinikä erityisesti operaation lohkossa. Nimikonfliktit. Muuttujat operaation alussa vai myöhemmin? 16.2 Lohkot Kaarisulut

Lisätiedot

Lohkot. if (ehto1) { if (ehto2) { lause 1;... lause n; } } else { lause 1;... lause m; } 15.3

Lohkot. if (ehto1) { if (ehto2) { lause 1;... lause n; } } else { lause 1;... lause m; } 15.3 15. Lohkot 15.1 Sisällys Tutustutaan lohkoihin. Muuttujien ja vakioiden näkyvyys sekä elinikä erityisesti operaation lohkossa. Nimikonfliktit. Muuttujat operaation alussa vai myöhemmin? 15.2 Lohkot Aaltosulkeet

Lisätiedot

Ohjelmointitaito (ict1td002, 12 op) Kevät Java-ohjelmoinnin alkeita. Tietokoneohjelma. Raine Kauppinen

Ohjelmointitaito (ict1td002, 12 op) Kevät Java-ohjelmoinnin alkeita. Tietokoneohjelma. Raine Kauppinen Ohjelmointitaito (ict1td002, 12 op) Kevät 2009 Raine Kauppinen raine.kauppinen@haaga-helia.fi 1. Java-ohjelmoinnin alkeita Tietokoneohjelma Java-kieli ja Eclipse-kehitysympäristö Java-ohjelma ja luokka

Lisätiedot

15. Ohjelmoinnin tekniikkaa 15.1

15. Ohjelmoinnin tekniikkaa 15.1 15. Ohjelmoinnin tekniikkaa 15.1 Sisällys For-each-rakenne. Lueteltu tyyppi enum. Override-annotaatio. Geneerinen ohjelmointi. 15.2 For-each-rakenne For-rakenteen variaatio taulukoiden ja muiden kokoelmien

Lisätiedot

Informaatioteknologian laitos Olio-ohjelmoinnin perusteet / Salo 15.2.2006

Informaatioteknologian laitos Olio-ohjelmoinnin perusteet / Salo 15.2.2006 TURUN YLIOPISTO DEMO III Informaatioteknologian laitos tehtävät Olio-ohjelmoinnin perusteet / Salo 15.2.2006 1. Tässä tehtävässä tarkastellaan erääntyviä laskuja. Lasku muodostaa oman luokkansa. Laskussa

Lisätiedot

2. Olio-ohjelmoinista lyhyesti 2.1

2. Olio-ohjelmoinista lyhyesti 2.1 2. Olio-ohjelmoinista lyhyesti 2.1 Sisällys Yleistä. Oliot ja luokat. Attribuutit. Olioiden esittely ja alustus. Rakentajat. Olion operaation kutsuminen. 2.2 Yleistä Olio-ohjelmointia käsitellään hyvin

Lisätiedot

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op. Poikkeukset ja tietovirrat: Virhetilanteiden ja syötevirtojen käsittely

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op. Poikkeukset ja tietovirrat: Virhetilanteiden ja syötevirtojen käsittely Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Poikkeukset ja tietovirrat: Virhetilanteiden ja syötevirtojen käsittely Poikkeukset Poikkeuksella tarkoitetaan yllättävää ajonaikaista tilannetta, joka

Lisätiedot

ITKP102 Ohjelmointi 1 (6 op)

ITKP102 Ohjelmointi 1 (6 op) ITKP102 Ohjelmointi 1 (6 op) Tentaattori: Antti-Jussi Lakanen 20. huhtikuuta 2018 Vastaa kaikkiin tehtäviin. Tee kukin tehtävä omalle konseptiarkille. Noudata ohjelmointitehtävissä kurssin koodauskäytänteitä.

Lisätiedot

12. Javan toistorakenteet 12.1

12. Javan toistorakenteet 12.1 12. Javan toistorakenteet 12.1 Sisällys Yleistä toistorakenteista. Laskurimuuttujat. While-, do-while- ja for-lauseet. Laskuri- ja lippumuuttujat. Tyypillisiä ohjelmointivirheitä. Silmukan rajat asetettu

Lisätiedot

Sisällys. 15. Lohkot. Lohkot. Lohkot

Sisällys. 15. Lohkot. Lohkot. Lohkot Sisällys 15. Lohkot Tutustutaan lohkoihin. Muuttujien ja vakioiden näkyvyys sekä elinikä erityisesti operaation lohkossa. Nimikonfliktit. Muuttujat operaation alussa vai myöhemmin? 15.1 15.2 Lohkot Aaltosulkeet

Lisätiedot

T Henkilökohtainen harjoitus: FASTAXON

T Henkilökohtainen harjoitus: FASTAXON T-76.115 Henkilökohtainen harjoitus: FASTAXON Suunnittelumallit Group: Muuntaja Pentti Vänskä 52572W 2 1. Toteutus Tämä henkilökohtainen harjoitustyö käsitteli suunnittelumallien (Design Patterns) käyttöä

Lisätiedot

ITKP102 Ohjelmointi 1 (6 op)

ITKP102 Ohjelmointi 1 (6 op) ITKP102 Ohjelmointi 1 (6 op) Tentaattori: Antti-Jussi Lakanen 7. huhtikuuta 2017 Vastaa kaikkiin tehtäviin. Tee jokainen tehtävä erilliselle konseptiarkille. Kirjoittamasi luokat, funktiot ja aliohjelmat

Lisätiedot

10 Lock Lock-lause

10 Lock Lock-lause 10 Lock Avainsanan lock (Lock keyword) avulla voidaan toteuttaa prosessien ja säikeiden välisessä keskinäisessä kommunikoinnissa käytettäviä synkronointi- ja poissuljentarakenteita. Tämän niin sanotun

Lisätiedot

Kompositio. Mikä komposition on? Kompositio vs. yhteyssuhde Kompositio Javalla Konstruktorit set-ja get-metodit tostring-metodi Pääohjelma

Kompositio. Mikä komposition on? Kompositio vs. yhteyssuhde Kompositio Javalla Konstruktorit set-ja get-metodit tostring-metodi Pääohjelma 1 Kompositio Mikä komposition on? Kompositio vs. yhteyssuhde Kompositio Javalla Konstruktorit set-ja get-metodit tostring-metodi Pääohjelma 1 Mikä kompositio on? Tili - : String - : double 1 1 Kayttoraja

Lisätiedot

5. HelloWorld-ohjelma 5.1

5. HelloWorld-ohjelma 5.1 5. HelloWorld-ohjelma 5.1 Sisällys Lähdekoodi. Lähdekoodin (osittainen) analyysi. Lähdekoodi tekstitiedostoon. Lähdekoodin kääntäminen tavukoodiksi. Tavukoodin suorittaminen. Virheiden korjaaminen 5.2

Lisätiedot

Luokka Murtoluku uudelleen. Kirjoitetaan luokka Murtoluku uudelleen niin, että murtolukujen sieventäminen on mahdollista.

Luokka Murtoluku uudelleen. Kirjoitetaan luokka Murtoluku uudelleen niin, että murtolukujen sieventäminen on mahdollista. 1 Luokka Murtoluku uudelleen Kirjoitetaan luokka Murtoluku uudelleen niin, että murtolukujen sieventäminen on mahdollista. Sievennettäessä tarvitaan osoittajan ja nimittäjän suurin yhteinen tekijä (syt).

Lisätiedot

Tietojen syöttäminen ohjelmalle. Tietojen syöttäminen ohjelmalle Scanner-luokan avulla

Tietojen syöttäminen ohjelmalle. Tietojen syöttäminen ohjelmalle Scanner-luokan avulla Tietojen syöttäminen ohjelmalle Tähän mennessä on käsitelty Javan tulostuslauseet System.out.print ja System.out.println sekä ohjelman perusrakenneosat (muuttujat, vakiot, lauseet). Jotta päästään tekemään

Lisätiedot

on ohjelmoijan itse tekemä tietotyyppi, joka kuvaa käsitettä

on ohjelmoijan itse tekemä tietotyyppi, joka kuvaa käsitettä LUOKAN MÄÄRITTELY Luokka, mitä se sisältää Luokan määrittely Olion ominaisuudet eli attribuutit Olion metodit Olion muodostimet ja luonti Olion tuhoutuminen Metodin kutsu luokan ulkopuolelta Olion kopioiminen

Lisätiedot

Sisällys. Yleistä attribuuteista. Näkyvyys luokan sisällä. Tiedonkätkentä. Aksessorit. 4.2

Sisällys. Yleistä attribuuteista. Näkyvyys luokan sisällä. Tiedonkätkentä. Aksessorit. 4.2 4. Attribuutit 4.1 Sisällys Yleistä attribuuteista. Näkyvyys luokan sisällä. Tiedonkätkentä. Aksessorit. 4.2 Yleistä Luokan lohkossa, mutta metodien ulkopuolella esiteltyjä muuttujia ja vakioita. Esittely

Lisätiedot

812341A Olio-ohjelmointi, IX Olioiden välisistä yhteyksistä

812341A Olio-ohjelmointi, IX Olioiden välisistä yhteyksistä 2016 IX Olioiden välisistä yhteyksistä Sisältö 1. Johdanto 2. Kytkentä 3. Koheesio 4. Näkyvyydestä 2 Johdanto n Ohjelmassa syntyy kytkentöjä olioiden välille Toivottuja ja epätoivottuja n Näkyvyys vaikuttaa

Lisätiedot

HOJ Säikeet (Java) Ville Leppänen. HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.1/55

HOJ Säikeet (Java) Ville Leppänen. HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.1/55 HOJ Säikeet (Java) Ville Leppänen HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.1/55 Missä mennään... 1. Johdanto (1h) 2. Säikeet (2h) 3. Samanaikaisuudesta (2h) 4. Hajautetuista sovelluksista (1h)

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 28.2.2011 T-106.1208 Ohjelmoinnin perusteet Y 28.2.2011 1 / 46 Ohjelmointiprojektin vaiheet 1. Määrittely 2. Ohjelman suunnittelu (ohjelman rakenne ja ohjelman

Lisätiedot

Java-kielen perusteita

Java-kielen perusteita Java-kielen perusteita Käyttäjän kanssa keskusteleva ohjelma 1 Kirjoittaminen konsolinäkymään //Java ohjelma, joka tulostaa konsoli-ikkunaan public class HeiMaailma { public void aja() { // kirjoitus ja

Lisätiedot

Poikkeustenkäsittely

Poikkeustenkäsittely 1 Poikkeustenkäsittely Mitä poikkeustenkäsittely tarkoittaa? Poikkeuksen käsitteleminen Poikkeusluokkien hierarkia Poikkeuksen heittäminen 1 Mitä poikkeustenkäsittely tarkoittaa? Poikkeus (Exception) on

Lisätiedot

Sisällys. Yleistä attribuuteista. Näkyvyys luokan sisällä ja ulkopuolelta. Attribuuttien arvojen käsittely aksessoreilla. 4.2

Sisällys. Yleistä attribuuteista. Näkyvyys luokan sisällä ja ulkopuolelta. Attribuuttien arvojen käsittely aksessoreilla. 4.2 4. Attribuutit 4.1 Sisällys Yleistä attribuuteista. Näkyvyys luokan sisällä ja ulkopuolelta. Attribuuttien arvojen käsittely aksessoreilla. 4.2 Yleistä Luokan lohkossa, mutta metodien ulkopuolella esiteltyjä

Lisätiedot

4. Luokan testaus ja käyttö olion kautta 4.1

4. Luokan testaus ja käyttö olion kautta 4.1 4. Luokan testaus ja käyttö olion kautta 4.1 Olion luominen luokasta Java-kielessä olio määritellään joko luokan edustajaksi tai taulukoksi. Olio on joukko keskusmuistissa olevia tietoja. Oliota käsitellään

Lisätiedot

Luokat ja oliot. Ville Sundberg

Luokat ja oliot. Ville Sundberg Luokat ja oliot Ville Sundberg 12.9.2007 Maailma on täynnä olioita Myös tietokoneohjelmat koostuvat olioista Σ Ο ω Μ ς υ φ Ϊ Φ Θ ψ Љ Є Ύ χ Й Mikä on olio? Tietokoneohjelman rakennuspalikka Oliolla on kaksi

Lisätiedot

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op. Tietorakenneluokkia 2: HashMap, TreeMap

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op. Tietorakenneluokkia 2: HashMap, TreeMap Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Tietorakenneluokkia 2: HashMap, TreeMap Tietorakenneluokkia ja -rajapintoja Java tarjoaa laajan kokoelman tietorakennerajapintoja ja - luokkia. Aiemmin

Lisätiedot

JAVA-OHJELMOINTI 3 op A274615

JAVA-OHJELMOINTI 3 op A274615 JAVA-OHJELMOINTI 3 op A274615 JFC & Swing, Look & Feel, Events Teemu Saarelainen teemu.saarelainen@kyamk.fi Lähteet: http://java.sun.com/docs/books/tutorial/index.html Vesterholm, Kyppö: Java-ohjelmointi,

Lisätiedot

58131 Tietorakenteet ja algoritmit (syksy 2015)

58131 Tietorakenteet ja algoritmit (syksy 2015) 58131 Tietorakenteet ja algoritmit (syksy 2015) Harjoitus 2 (14. 18.9.2015) Huom. Sinun on tehtävä vähintään kaksi tehtävää, jotta voit jatkaa kurssilla. 1. Erään algoritmin suoritus vie 1 ms, kun syötteen

Lisätiedot

Arto Salminen,

Arto Salminen, 4. Luento: Prosessit ja säikeet Arto Salminen, arto.salminen@tut.fi Agenda Prosessi Säikeet Keskeytykset Keskeytyskäsittely Käyttöjärjestelmäkutsut Prosessielementti Prosessin hallinta Suunnittelunäkökohtia

Lisätiedot

Semaforit Javassa. Mari Kononow, Eveliina Mattila, Sindi Poikolainen HELSINGIN YLIOPISTO

Semaforit Javassa. Mari Kononow, Eveliina Mattila, Sindi Poikolainen HELSINGIN YLIOPISTO Semaforit Javassa Mari Kononow, Eveliina Mattila, Sindi Poikolainen 13.12.2008 HELSINGIN YLIOPISTO Tietojenkäsittelytieteen laitos Ohjetta saa käyttää opetukseen ja jatkokehitykseen Johdanto Semaforeja

Lisätiedot

1 Tehtävän kuvaus ja analysointi

1 Tehtävän kuvaus ja analysointi Olio-ohjelmoinnin harjoitustyön dokumentti Jyri Lehtonen (72039) Taneli Tuovinen (67160) 1 Tehtävän kuvaus ja analysointi 1.1 Tehtävänanto Tee luokka, jolla mallinnetaan sarjaan kytkettyjä kondensaattoreita.

Lisätiedot

Ongelma(t): Miten tietokoneen käyttöjärjestelmä toimii sisäisesti, jotta resurssit saadaan tehokkaaseen käyttöön?

Ongelma(t): Miten tietokoneen käyttöjärjestelmä toimii sisäisesti, jotta resurssit saadaan tehokkaaseen käyttöön? Ongelma(t): Miten tietokoneen käyttöjärjestelmä toimii sisäisesti, jotta resurssit saadaan tehokkaaseen käyttöön? 2013-2014 Lasse Lensu 2 Systeemiohjelmat ovat tietokoneen laitteistoa lähellä olevia ohjelmia,

Lisätiedot

5. HelloWorld-ohjelma 5.1

5. HelloWorld-ohjelma 5.1 5. HelloWorld-ohjelma 5.1 Sisällys Lähdekoodi. Lähdekoodin (osittainen) analyysi. Lähdekoodi tekstitiedostoon. Lähdekoodin kääntäminen tavukoodiksi. Tavukoodin suorittaminen. Virheiden korjaaminen 5.2

Lisätiedot

Java-kielen perusteet

Java-kielen perusteet Java-kielen perusteet Tunnus, varattu sana, kommentti Muuttuja, alkeistietotyyppi, merkkijono, Vakio Tiedon merkkipohjainen tulostaminen Ohjelmointi (ict1tx006) Tunnus (5.3) Javan tunnus Java-kirjain Java-numero

Lisätiedot

Java-kielen perusteita

Java-kielen perusteita Java-kielen perusteita valintalauseet 1 Johdantoa kontrollirakenteisiin Tähän saakka ohjelmissa on ollut vain peräkkäisyyttä eli lauseet on suoritettu peräkkäin yksi kerrallaan Tarvitsemme myös valintaa

Lisätiedot

812347A Olio-ohjelmointi, 2015 syksy 2. vsk. X Poikkeusten käsittelystä

812347A Olio-ohjelmointi, 2015 syksy 2. vsk. X Poikkeusten käsittelystä 812347A Olio-ohjelmointi, 2015 syksy 2. vsk X Poikkeusten käsittelystä Sisältö 1. Yleistä poikkeusten käsittelystä 2. Poikkeuskäsittelyn perusteita C++:ssa 3. Standardissa määritellyt poikkeukset 4. Poikkeusvarmuus

Lisätiedot

4. Olio-ohjelmoinista lyhyesti 4.1

4. Olio-ohjelmoinista lyhyesti 4.1 4. Olio-ohjelmoinista lyhyesti 4.1 Sisällys Yleistä. Oliot ja luokat. Attribuutit. Olioiden esittely ja alustus. Rakentajat. Olion operaation kutsuminen. 4.2 Yleistä Olio-ohjelmointia käsitellään hyvin

Lisätiedot

Ohjelmoinnin perusteet, kurssikoe

Ohjelmoinnin perusteet, kurssikoe Ohjelmoinnin perusteet, kurssikoe 18.6.2014 Kirjoita jokaiseen konseptiin kurssin nimi, kokeen päivämäärä, nimi, TMC-tunnus ja opiskelijanumero tai henkilötunnus. Vastaukset palautetaan tehtäväkohtaisiin

Lisätiedot

4. Lausekielinen ohjelmointi 4.1

4. Lausekielinen ohjelmointi 4.1 4. Lausekielinen ohjelmointi 4.1 Sisällys Konekieli, symbolinen konekieli ja lausekieli. Lausekielestä konekieleksi: - Lähdekoodi, tekstitiedosto ja tekstieditorit. - Kääntäminen ja tulkinta. - Kääntäminen,

Lisätiedot

Oliosuunnitteluesimerkki: Yrityksen palkanlaskentajärjestelmä

Oliosuunnitteluesimerkki: Yrityksen palkanlaskentajärjestelmä Oliosuunnitteluesimerkki: Yrityksen palkanlaskentajärjestelmä Matti Luukkainen 10.12.2009 Tässä esitetty esimerkki on mukaelma ja lyhennelmä Robert Martinin kirjasta Agile and Iterative Development löytyvästä

Lisätiedot

TIEP114 Tietokoneen rakenne ja arkkitehtuuri, 3 op. Assembly ja konekieli

TIEP114 Tietokoneen rakenne ja arkkitehtuuri, 3 op. Assembly ja konekieli TIEP114 Tietokoneen rakenne ja arkkitehtuuri, 3 op Assembly ja konekieli Tietokoneen ja ohjelmiston rakenne Loogisilla piireillä ja komponenteilla rakennetaan prosessori ja muistit Prosessorin rakenne

Lisätiedot

TIEP114 Tietokoneen rakenne ja arkkitehtuuri, 3 op. Assembly ja konekieli

TIEP114 Tietokoneen rakenne ja arkkitehtuuri, 3 op. Assembly ja konekieli TIEP114 Tietokoneen rakenne ja arkkitehtuuri, 3 op Assembly ja konekieli Tietokoneen ja ohjelmiston rakenne Loogisilla piireillä ja komponenteilla rakennetaan prosessori ja muistit Prosessorin rakenne

Lisätiedot

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Pakkaukset ja määreet

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Pakkaukset ja määreet Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Pakkaukset ja määreet Pakkaukset ja määreet Toisiinsa liittyvät luokkatiedostot voidaan koota pakkauksiksi. Luo hierarkiaa ja järjestystä ohjelmistotuotteeseen.

Lisätiedot

Rinnakkaisuuden hyväksikäyttö peleissä. Paula Kemppi

Rinnakkaisuuden hyväksikäyttö peleissä. Paula Kemppi Rinnakkaisuuden hyväksikäyttö peleissä Paula Kemppi 24.4.2008 Esityksen rakenne Johdantoa Rinnakkaisuus Pelimoottorien rinnakkaisuuden mallit Funktionaalisen rinnakkaisuuden malli Rinnakkaisen tiedon malli

Lisätiedot

Sisällys. 11. Javan toistorakenteet. Laskurimuuttujat. Yleistä

Sisällys. 11. Javan toistorakenteet. Laskurimuuttujat. Yleistä Sisällys 11. Javan toistorakenteet Laskuri- ja lippumuuttujat.. Tyypillisiä ohjelmointivirheitä: Silmukan rajat asetettu kierroksen verran väärin. Ikuinen silmukka. Silmukoinnin lopettaminen break-lauseella.

Lisätiedot

Tietorakenteet (syksy 2013)

Tietorakenteet (syksy 2013) Tietorakenteet (syksy 2013) Harjoitus 1 (6.9.2013) Huom. Sinun on osallistuttava perjantain laskuharjoitustilaisuuteen ja tehtävä vähintään kaksi tehtävää, jotta voit jatkaa kurssilla. Näiden laskuharjoitusten

Lisätiedot

9. Periytyminen Javassa 9.1

9. Periytyminen Javassa 9.1 9. Periytyminen Javassa 9.1 Sisällys Periytymismekanismi Java-kielessä. Piirteiden näkyvyys periytymisessä. Metodien korvaaminen ja super-attribuutti. Attribuutin peittäminen periytymisen kautta. Rakentajat

Lisätiedot

1. Omat operaatiot 1.1

1. Omat operaatiot 1.1 1. Omat operaatiot 1.1 Sisällys Yleistä operaatioista. Mihin operaatioita tarvitaan? Oman operaation määrittely. Yleisesti, nimeäminen ja hyvä ohjelmointitapa, määreet, parametrit ja näkyvyys. HelloWorld-ohjelma

Lisätiedot

15. Ohjelmoinnin tekniikkaa 15.1

15. Ohjelmoinnin tekniikkaa 15.1 15. Ohjelmoinnin tekniikkaa 15.1 Sisällys For-each-rakenne. Geneerinen ohjelmointi. Lueteltu tyyppi enum. 15.2 For-each-rakenne For-rakenteen variaatio taulukoiden ja muiden kokoelmien silmukoimiseen:

Lisätiedot

11/20: Konepelti auki

11/20: Konepelti auki Ohjelmointi 1 / syksy 2007 11/20: Konepelti auki Paavo Nieminen nieminen@jyu.fi Tietotekniikan laitos Informaatioteknologian tiedekunta Jyväskylän yliopisto Ohjelmointi 1 / syksy 2007 p.1/11 Tämän luennon

Lisätiedot