diff --git a/answers.md b/answers.md index 87e291b5d70a189d7a1a93fb85ef8ea6e046456b..ab4346dd5bb42eb2f4afae44186498b4013b392e 100644 --- a/answers.md +++ b/answers.md @@ -2,10 +2,18 @@ Vastaa tehtävän 3 kysymyksiin tässä tiedostossa. Vastaa suomeksi. Use this file to answer to the questions in exercise 3 # Question 1: Program structure -Your answer here +Threadrunner2-ohjelma havainnollistaa töiden jakamista säikeille. Graafinen käyttöliittymä antaa käyttäjälleen mahdollisuuden generoida haluamansa määrän töitä haluamillaan ominaisuuksilla sekä valita töitä suorittavien säikeiden määrän ja kerrallaan säikeen työstöön ottamien töiden määrän. Töiden määrittelyssä on tarjolla kaksi tehtävätyyppiä sekä kolme eri kuormittavuutta. Töitä suorittamaan voi valita halutun määrän säikeitä yhdestä aina koneen suorittimen ytimien lukumäärän määrittämään maksimiin saakka. +Oleellisin valinta liittyy säietyypin valintaan. Käyttäjä voi suorittaa töitä työlistalta yhdellä säikeellä (”Single”), jolloin rinnakkaisia säikeitä ei käytetä. Vaihtoehtoisesti töitä voi suorittaa usealla säikeellä joko valinnalla ”Thread” tai ”Executor”. Käyttäjän näkökulmasta näiden kahden valinnan välillä ei ole eroavaisuuksia, mutta konepellin alla tapahtuu valinnasta riippuen erilaisia asioita. +Kolmen säikeiden toimintaa ohjaavan toteutuksen tueksi ohjelmasta löytyvät luokat Mediator sekä ControlSet, jotka välittävät tietoa ohjelman eri osien välillä. ControlSet-luokan oliot sisältävät valittujen säikeiden sekä kerralla työstettävien töiden määrän Mediator-luokan olioiden välittäessä tietoa käyttöliittymälle. +Yhden säikeen ajossa käytetään ohjelman Thread-luokan perivän esimerkkiluokan oliota. Olio saa konstruktorissa parametreikseen mediatorin sekä controllin ja sille on luotu luokassa omat suoritusmetodit. Luokan run() käy läpi työlistan, merkitsee töiden statuksen ja suorittaa ne ennen valmiiksi merkitsemistä. Kaikki työstäminen tapahtuu yhden säikeen toimesta. +Monen säikeen yhtäaikaisen ajon ensimmäinen toteutus (”Thread”-valinta) on luotu perusajatukseltaan esimerkkiluokan (”Single”-valinta) pohjalta, mutta luokka itsessään ei peri Thread-luokkaa vaan tukeutuu erilliseen, Thread-luokan perivään MyThread-luokkaan. MyThread-luokassa luodaan säie, jolle annetaan parametreiksi mediator sekä control. Luokassa on määritelty metodit ajoa ja rekisteröintiä varten. Yksittäisen säikeen run() käy saamaansa työlistaa läpi kuten ”Single”-valinnan toteutus. Monen säikeen toteutuksessa yksittäisiä, oman luokkansa pohjalta toteutettuja säieolioita kerätään käyttäjän valitsema määrä listaan, säikeet rekisteröidään ja kukin säie laitetaan suorittamaan töitä. Työt jakautuvat säikeille käyttäjän valinnan mukaisina blokkeina ja niitä suoritetaan, kunnes työlista on käyty kokonaan läpi. +”Executor”-valinta on ratkaistu Runnable-rajapinnan toteuttavaa MyRunnable-luokkaa apuna käyttäen. Valinnan toteuttavassa luokassa luodaan ExecutorService, eli Runnable-olioiden suorittamiseen erikoistunut olio, jolle luodaan for-silmukalla käyttäjän haluama määrä MyRunnable-luokan oloita suoritettavaksi rajapinnan execute-metodilla. Lopuksi ExecutorService sammutetaan viemästä muistia. + # Question 2: More threads than cores -Your answer here +Mikäli säikeet eivät vaadi I/O-operaatioita ja niiden valmistumisen odottamista, on optimaalisinta sovittaa suoritettavien säikeiden määrä ytimien määrän kanssa, sillä kontekstinvaihdokset vain hidastavat laskentaa Käytännössä asia menee harvoin näin, joten suoritusajaltaan optimaalisen tuloksen saa testaamalla eli suorittamalla eri määriä säikeitä ja kellottamalla aikoja. +Luentomonistetta lainaten on syytä muistaa, että ”-- käytettävien säikeiden määrä pitää suhteuttaa saatavilla olevien ytimien määrään: neljällä ytimellä ei ole CPU-intensiivisissä tehtävissä järkevää laskea neljääsataa osaongelmaa samanaikaisesti: aikataulutus kyllä mahdollistaa tämän, mutta tehokkuus ei kasva - päin vastoin, lisääntyneet”. # Question 3: workQueue -Your answer here +ArrayList ei itsessään ole säieturvallinen ratkaisu töiden listaamiseen. Javan dokumentaation mukaisesti usean säikeen päästessä käsiksi listan elementteihin se on synkronoitava ulkoisesti joka kerta, kun yksikin säie tekee listaan muutoksia. Lista voidaan tehdä säieturvalliseksi ArrayListin variantilla CopyOnWriteArrayList, joka luo aina listaa muokkaavan operaation yhteydessä tuoreen kopion listasta. Tämä syö kuitenkin resursseja, joten ratkaisu on järkevä lähinnä tilanteissa, joissa säikeet lähinnä lukevat tietoa listasta ja tekevät siihen muutoksia vain harvakseltaan. +LinkedBlockingQueue käyttää FIFO-menetelmää (first-in-first-out), eli jonon kärjessä on aina sinne ensimmäisenä listattu elementti. Näin ollen työskentelijäsäikeiden toimiessa jonoon lisätyt työt menevät jonon perään aiempien töiden jatkoksi. Lisäksi jonossa on nimensä mukaisesti sisäinen lukitus, joka tekee jonosta säieturvallisen. diff --git a/src/main/java/fi/utu/tech/threadrunner2/assignment/MyThread.java b/src/main/java/fi/utu/tech/threadrunner2/assignment/MyThread.java index 6e91dbf3694480d63d8e0d7e6d502f664c1a9838..b15339f40edeaecd2ed8348d5cca43015a2bdb53 100644 --- a/src/main/java/fi/utu/tech/threadrunner2/assignment/MyThread.java +++ b/src/main/java/fi/utu/tech/threadrunner2/assignment/MyThread.java @@ -30,7 +30,7 @@ public class MyThread extends Thread { } } - // Set thread status to ended when worklist is empty + // Set thread status to ended when work list is empty mediator.setRunStatus("Ended", this.hashCode()); }