Вы находитесь на странице: 1из 129

Потоки демоны

Создание потоков демонов

public class SDaemons extends Thread


{ public Sdaemons()
{setDaemon(true);
start();}
public void run()
{while(true)
{try
{sleep(100);}
catch (InterruptedException e)
{throw new RuntimeException(e);}
System.out.println(this);}}
public static void main (String[]args)
{for(int i=0; i<10; i++)
new SDaemons();}}
Чтобы проверить является ли поток демоном используется метод isDaemon()

class Daemon extends Thread


{ private static final int SIZE = 10;
private Thread[] t = new Thread[SIZE];
public Daemon()
{ setDaemon(true);
start(); }
public void run()
{ for(int i = 0; i < SIZE; i++)
t[i] = new DaemonSpawn(i);
for(int i = 0; i < SIZE; i++)
System.out.println( "t[" + i + "].isDaemon() = " + t[i].isDaemon());
while(true) yield(); } }
class DaemonSpawn extends Thread
{ public DaemonSpawn(int i)
{ System.out.println( "DaemonSpawn " + i + " started"); start(); }
public void run()
{ while(true) yield(); } }
public class Daemons
{ public static void main(String[] args)
throws IOException
{ Thread d = new Daemon();
System.out.println( "d.isDaemon() = " + d.isDaemon());
System.out.println("Press any key"); System.in.read(); }
Результат программы

Поток демона 0 запущен


Поток демона 1 запущен
Поток демона 2 запущен
Поток демона 3 запущен
Поток демона 4 запущен
Поток демона 5 запущен
Поток демона 6 запущен
Поток демона 7 запущен
Поток демона 8 запущен
Поток демона 9 запущен
t[0].isDaemon()=true
t[1].isDaemon()=true
t[2].isDaemon()=true
t[3].isDaemon()=true
t[4].isDaemon()=true
t[5].isDaemon()=true
t[6].isDaemon()=true
t[7].isDaemon()=true
t[8].isDaemon()=true
t[9].isDaemon()=true
Приоритеты настраиваются методом setPriority()

public class SPriority extends Thread


{private int countD=5;
private volatile double d=0; \\ без оптимизации
public SPriority(int priority)
{setPriority(priority);
start();}
public String toString
{return super.toString() + “:” + countD;}
public void run()
{while(true)
for(int i=0; i<100000; i++)
d=d+(Math.PI+Math.E)/(double)i;
System.out.println(this)
If(--countD==0) return;}}
public static void main(String[]args)
{new SPriority(Thread.MAX_PRIORITY);
for(int i=0; i<5; i++)
new SPriority (Thread.MIN_PRIORITY);}}
Результат программы

Thread[Thread-1.10.main]:5 Thread[Thread-4.1.main]:4
Thread[Thread-1.10.main]:4 Thread[Thread-5.1.main]:4
Thread[Thread-1.10.main]:3 Thread[Thread-6.1.main]:4
Thread[Thread-1.10.main]:2 Thread[Thread-3.1.main]:3
Thread[Thread-1.10.main]:1 Thread[Thread-4.1.main]:3
Thread[Thread-2.1.main]:5 Thread[Thread-5.1.main]:3
Thread[Thread-2.1.main]:4 Thread[Thread-6.1.main]:3
Thread[Thread-2.1.main]:3 Thread[Thread-3.1.main]:2
Thread[Thread-2.1.main]:2 Thread[Thread-4.1.main]:2
Thread[Thread-2.1.main]:1 Thread[Thread-5.1.main]:2
Thread[Thread-3.1.main]:5 Thread[Thread-6.1.main]:2
Thread[Thread-4.1.main]:5 Thread[Thread-4.1.main]:1
Thread[Thread-5.1.main]:5 Thread[Thread-3.1.main]:1
Thread[Thread-6.1.main]:5 Thread[Thread-6.1.main]:1
Thread[Thread-3.1.main]:4 Thread[Thread-5.1.main]:1
Группы потоков

public class TestAccess


{ public static void main(String[] args)
{ ThreadGroup
x = new ThreadGroup("x"),
y = new ThreadGroup(x, "y"),
z = new ThreadGroup(y, "z");
Thread one = new TestThread1(x, "one"),
two = new TestThread2(z, "two"); }}
class TestThread1 extends Thread
{ private int i;
TestThread1(ThreadGroup g, String name)
{ super(g, name); } void f() { i++;
System.out.println(getName() + " f()"); }}
class TestThread2 extends TestThread1
{ TestThread2(ThreadGroup g, String name)
{ super(g, name); start(); }
public void run()
{ ThreadGroup g = getThreadGroup().getParent().getParent();
g.list();
Thread[] gAll = new Thread[g.activeCount()];
g.enumerate(gAll); for(int i = 0; i < gAll.length; i++)
{ gAll[i].setPriority(Thread.MIN_PRIORITY);
((TestThread1)gAll[i]).f(); }
g.list(); }}
Отладочный метод list() выводит всю информацию о группе

процессов на стандартный вывод.

java.lang.ThreadGroup[name=x,maxpri=10]
Thread[one,5,x]
java.lang.ThreadGroup[name=y,maxpri=10]
java.lang.ThreadGroup[name=z,maxpri=10]
Thread[two,5,z]
one f()
two f() java.lang.ThreadGroup[name=x,maxpri=10]
Thread[one,1,x]
java.lang.ThreadGroup[name=y,maxpri=10]
java.lang.ThreadGroup[name=z,maxpri=10]
Thread[two,1,z]
Управление группами процессов

public class ThreadGroup1


{ public static void main(String[] args)
{ ThreadGroup sys = Thread.currentThread().getThreadGroup();
sys.list();
// (1)
sys.setMaxPriority(Thread.MAX_PRIORITY - 1);
Thread curr = Thread.currentThread();
curr.setPriority(curr.getPriority() + 1);
sys.list();
// (2)
ThreadGroup g1 = new ThreadGroup("g1");
g1.setMaxPriority(Thread.MAX_PRIORITY);
Thread t = new Thread(g1, "A");
t.setPriority(Thread.MAX_PRIORITY);
g1.list();
// (3)
g1.setMaxPriority(Thread.MAX_PRIORITY - 2);
g1.setMaxPriority(Thread.MAX_PRIORITY);
g1.list();
// (4)
t = new Thread(g1, "B"); t.setPriority(Thread.MAX_PRIORITY);
g1.list();
// (5)
g1.setMaxPriority(Thread.MIN_PRIORITY + 2);
t = new Thread(g1, "C");
g1.list();
// (6)
t.setPriority(t.getPriority() -1);
Gruparea și modificarea priorității thread-urilor

public class ThreadGroup1


{ public static void main(String[] args)
{ ThreadGroup sys =
Thread.currentThread().getThreadGroup();
sys.list();
// (1)
sys.setMaxPriority(Thread.MAX_PRIORITY - 1);
Thread curr = Thread.currentThread();
curr.setPriority(curr.getPriority() + 1);
sys.list();
//(2)
Rezultatul realizării

• (1)ThreadGroup[name=system,maxpri=10]
• Thread[main,5,system]
• (2) ThreadGroup[name=system,maxpri=9]
• Thread[main,6,system]
• (1) Numele grupului de bază este system,
numele procesului principal este main și
aparține grupului system
• (2) Implicit prioritatea grupului este 10 și
micșorăm la 9. Implicit prioritatea thread-ului
este 5 și mărim la 6.
continuare
ThreadGroup g1 = new ThreadGroup("g1");

g1.setMaxPriority(Thread.MAX_PRIORITY);

Thread t = new Thread(g1, "A");

t.setPriority(Thread.MAX_PRIORITY);

g1.list();
// (3)
Rezultatul realizării

(3) ThreadGroup[name=g1,maxpri=9]
Thread[A,9,g1]

Se crează grupul g1 care automat este inclusă în


grupul de sistemă. Se crează thread-ul A inclus în
grupul g1.
Nu se poate de modificat prioritatea grupului mai
mare ca proiritatea grupului căruia îi aparține.
Nu se pote de modificat ptioritatea thread-ului mai
mare ca pioritatea grupului fr sistemă.
continuare

g1.setMaxPriority(Thread.MAX_PRIORITY - 2);

g1.setMaxPriority(Thread.MAX_PRIORITY);

g1.list();
// (4)
Rezultatul realizării

(4) ThreadGroup[name=g1,maxpri=8]
Thread[A,9,g1]

Prioritatea grupului se poate numai de


micșorat și nu poate fi mărit. Prioritatea
thread-ului rămîne aceiaș.
continuare

t = new Thread(g1, "B");


t.setPriority(Thread.MAX_PRIORITY);
g1.list();
// (5)
Rezultatul realizării

(5) ThreadGroup[name=g1,maxpri=8]
Thread[A,9,g1]
Thread[B,8,g1]
Implicit prioritatea thread-ului creat este 6 ca
proiritatea procesului de sistemă. Dar la
modificare nu pote fi mai mare ca prioritatea
grupului căruia îi aparține.
continuare

g1.setMaxPriority(Thread.MIN_PRIORITY + 2);
t = new Thread(g1, "C");
g1.list();
// (6)
Rezultatul realizării

(6) ThreadGroup[name=g1,maxpri=3]
Thread[A,9,g1]
Thread[B,8,g1]
Thread[C,6,g1]
Dacă prioritatea grupului este mai mică ca
prioritatea procesului de sistemă, atunci
prioritatea thread-ului creat în grupul g1 va
primi prioritatea mai mare ca prioritatea
grupului egală cu prioritatea procesului de
sistemă.
continuare

// (6)
t.setPriority(t.getPriority() -1);
g1.list();
Rezultatul realizării

ThreadGroup[name=g1,maxpri=3]
Thread[A,9,g1]
Thread[B,8,g1]
Thread[C,3,g1]
Результат программы будет
(1) ThreadGroup[name=system,maxpri=10]
Thread[main,5,system]
(2) ThreadGroup[name=system,maxpri=9]
Thread[main,6,system]
(3) ThreadGroup[name=g1,maxpri=9]
Thread[A,9,g1]
(4) ThreadGroup[name=g1,maxpri=8]
Thread[A,9,g1]
(5) ThreadGroup[name=g1,maxpri=8]
Thread[A,9,g1]
Thread[B,8,g1]
(6) ThreadGroup[name=g1,maxpri=3]
Thread[A,9,g1]
Thread[B,8,g1]
Thread[C,6,g1]
(7) ThreadGroup[name=g1,maxpri=3]
Thread[A,9,g1]
Thread[B,8,g1]
Thread[C,3,g1]
(8) ThreadGroup[name=g2,maxpri=3]
(9) ThreadGroup[name=g2,maxpri=3]
(10)ThreadGroup[name=system,maxpri=9]
Thread[main,6,system]
ThreadGroup[name=g1,maxpri=3]
Thread[A,9,g1]
Thread[B,8,g1]
Thread[C,3,g1]
ThreadGroup[name=g2,maxpri=3]
Thread[0,6,g2]
Thread[1,6,g2]
Thread[2,6,g2]
Thread[3,6,g2]
Thread[4,6,g2]
Clasa Thread
Sincronizarea thread-urilor cu yield()
public class SimpleThread1 extends Thread
{
private int countDown = 5;
private static int threadCount = 0;
private int threadNumber = ++threadCount;
public SimpleThread1()
{
System.out.println("Making " + threadNumber); }
public void run()
{
while(true)
{ System.out.println("Thread " + threadNumber + "(" + countDown + ")");
if(--countDown == 0) return;
yield();
}}
public static void main(String[] args)
{
for(int i = 0; i < 5; i++)
new SimpleThread1().start();
System.out.println("All Threads Started");
}}
Sincronizarea thread-urilor cu sleep()
public class SimpleThread extends Thread
{
private int countDown = 5;
private static int threadCount = 0;
private int threadNumber = ++threadCount;
public SimpleThread()
{
System.out.println("Making " + threadNumber); }
public void run()
{
while(true)
{ System.out.println("Thread " + threadNumber + "(" + countDown + ")");
if(--countDown == 0) return;
try{ sleep(100);}
Catch (InterruptedException e)
{
Throw new RuntimeException(e);}
}}
public static void main(String[] args)
{
for(int i = 0; i < 5; i++)
new SimpleThread().start();
System.out.println("All Threads Started");
Metodele clasei Thread
Constructorii
 Crearea unui nou obiect Thread
 public Thread();
 Crearea unui nou obiect Thread cu indicarea obiectului pentru care
va fi activată metoda run().
 public Thread(Runnable target);
 Analogic constructorului precedent, dar se indică ți numele
obiectului Thread
 public Thread(Runnable target, String name);
 Crearea unui nou obiect Thread și se indică numele lui.
 public Thread(String name);
 Crearea unui nou obiect Thread, se indică numele grupului căruia îi
aparâine și obiectul pentru cae va fi activată metoda run().
 public Thread(ThreadGroup group, Runnable target);
 Analogic constructorului precedent, dar se indică ți numele
obiectului Thread
 public Thread(ThreadGroup group, Runnable target, String
name); Crearea unui nou obiect Thread cu indicarea numelui
grupului căruia îi aparâine și numele lui.
 public Thread(ThreadGroup group, String name);
Metodele
 activeCount apreciază numărul de thread-uri active din grupul
căruia îi aparâine
 public static int activeCount();

 currentThread apreciază thread-ul curent activ


 public static Thread currentThread();

 destroy finalifarea forțată a thread-ului


 public void destroy();

 enumerate apreciază toate thread-urile din grupa dată.


 public static int enumerate(Thread tarray[]);

 getName apreciază numele thread-ului.


 public final String getName();

 getPriority apreciază prioritatea curentă a thread-ului


 public final int getPriority();
continuare

 getThreadGroup apreciază grupul căruia îi aparține thread-ul


 public final ThreadGroup getThreadGroup();

 interrupt întrerupe realizarea thread-ului


 public void interrupt();

 Interrupted aptreciază dacă thread-ul este întrerupt


 public static boolean interrupted();

 isAlive apreciază dacă thread-ul se realizează sau nu


 public final boolean isAlive();

 isDaemon apreciază este thread-ul daemon


 public final boolean isDaemon();

 resume restartarea thread-ului temporar oprit


 public final void resume();
continuare
 join așteaptă realizarea complectă a thread-ului sau așteaptă
realizarea thread-ului pe parcursul timpului indicat în milisecunde și
nanosecunde
 public final void join();
 public final void join(long millis);
public final void join(long millis, int nanos);

 run metoda este activată pentru a realiza thread-ul


 public void run();

 setDaemon indică că thread-ul creat va fi daemon


 public final void setDaemon(boolean on);

 setName atribue nume thread-ului


 public final void setName(String name);

 yield oprește temporar thread-ul activ a transmite comanda altui


thread
 public static void yield();
continuarе
 setPriority instalarea priorității
 public final void setPriority(int newPriority);

 sleep ”adormirea” thread-ului pe timpul indicat în milisecunde și


nanosecunde
 public static void sleep(long millis);
 public static void sleep(long millis, int nanos);

 start activarea thread-ului


 public void start();

 stop dezactivarea finală a thread-urilor


 public final void stop();

 suspend dezactivarea temporară a thread-ului


 public final void suspend();
Problema producatorului si a consumatorului
class MyData {
private int Data;
public void store(int Data) {
this.Data=Data; }
public int load() {
return this.Data; } }
• class Main{
• public static void main(String argv[]) {
• MyData data = new MyData();
• new Thread(new Producer(data)).start();
• new Thread(new Consumer(data)).start(); } }
• class Producer implements Runnable {
• //Thread-ul - Producator
• MyData data;
• public Producer(MyData data) {
• this.data=data; }

continuare
• public void run() {
• int i;
• for (i=0;;i++) {
• data.store(i);
• System.out.println ("Producer: "+i);
• try { // "adormire" de 0 pina la 0.5 sec
• Thread.sleep ((int) (Math.random()*500));
• } catch (InterruptedException e) { } } } }
• class Consumer implements Runnable {
• MyData data;
• public Consumer(MyData data) {
• this.data=data; }
• public void run() {
• for (;;) {
• System.out.println ("Consumer: "+data.load());
• try {
• Thread.sleep ((int) (Math.random()*500));
• } catch (InterruptedException e) { } } } }
Rezultatul
• Producer: 0
• Consumer: 0
• Producer: 1
• Consumer: 1
• Consumer: 1
• Producer: 2
• Producer: 3
• Consumer: 3
• Producer: 4
• Producer: 5
• Consumer: 5
• Producer: 6
• Consumer: 6
• Producer: 7
• Consumer: 7
• Consumer: 7
• Producer: 8
• Producer: 9
• Producer: 10
• Consumer: 10
Folosirea variabeliior binare
• class MyData {
• private int Data;
• private boolean Ready;
• private boolean Taken;
• public MyData() {
• Ready=false;
• Taken=true; }
• public void store(int Data) {
• while (!Taken);
• this.Data=Data;
• Taken=false;
• Ready=true;
• }

continuare

• public int load() {


• int Data;
• while (!Ready);
• Data = this.Data; //Salvare, deoarece dupa ce
• //Taken devine true, Data se poate schimba oricand
• Ready=false;
• Taken=true;
• return Data;
• }
• }
Sincronizarea utilizand monitoare
• class MyData {
• private int Data;
• private boolean Ready;
• private boolean Taken;
• public MyData() {
• Ready=false;
• Taken=true; }
• public synchronized void store(int Data) {
• while (!Taken);
• this.Data=Data;
• Taken=false;
• Ready=true;
• }
continuare

• public synchronized int load() {


• while (!Ready);
• Ready=false;
• Taken=true;
• return this.Data;
• }
• }
synchronized pentru un segment de cod

• class MyData {
• private int Data;
• private boolean Ready;
• private boolean Taken;
• public MyData() {
• Ready=false;
• Taken=true; }
• public void store(int Data) {
• while (!Taken);
• synchronized (this) {
• this.Data=Data;
• Taken=false;
• Ready=true;
• }
• }
continuare

• public int load() {


• while (!Ready);
• synchronized (this) {
• Ready=false;
• Taken=true;
• return this.Data;
• }
• }
• }
Asteptarea de evenimente. Metodele wait() si notify()

• class MyData {
• private int Data;
• private boolean Ready;
• public MyData() {
• Ready=false;
• }
• public synchronized void store(int Data) {
• while (Ready)
• try {
• wait();
• } catch (InterruptedException e) { }
• this.Data=Data;
• Ready=true;
• notify();
• }
continuare

• public synchronized int load() {


• while (!Ready)
• try {
• wait();
• } catch (InterruptedException e) { }
• Ready=false;
• notify();
• return this.Data; } }
Bariere

• import java.util.*;
• class Barrier { // Clasa Barrier sincronizeaza toti
• //participantii private
• int ParticipatingThreads;
• private int WaitingAtBarrier;
• public Barrier(int num){ //Constructorul
obiectului
• ParticipatingThreads = num;
• WaitingAtBarrier=0;
• }
continuare

• public synchronized void Reached() { //Metoda bariera


• WaitingAtBarrier++;
• if ( ParticipatingThreads != WaitingAtBarrier ) { //Inseamna ca
thread-ul nu este ultimul
• try {
• wait(); //Thread-ul este oprit pina ce
• //este eliberat
• } catch (InterruptedException e) { } } else { // Acesta a fost ultimul
thread activ
• notifyAll();
• WaitingAtBarrier=0; // le elibereaza pe toate
• }
• }
• }
Asteptarea terminarii unui thread

• Class MainThread extends Thread


• {
• public void run()
• {
• SecondaryThread s = new SecondaryThread();
• s.start();
• if (s.isAlive())
• s.join();
• }
• }
Semafoare
• class Semaphore
• {
• protected int value;
• Semaphore( int initialValue )
• {
• value = initialValue; }
• Semaphore()
• {
• value = 0; }
• public synchronized void Get()
• {
• while (value<1)
• wait();
• value--; }
• public synchronized void Put()
• {
• value++;
• notify();
• }}
Servlete
Noțiuni de servlet
 Servlet-urile sunt aplicatii Java aflate pe server si executate de catre acesta.
Serverul de Web, la executarea servlet-ului, trimite înapoi browser-ului un
fisier HTML, pe care acesta îl afiseaza corespunzator; în particular, browser-ul
nu trebuie sa stie nici macar ce înseamna un servlet.
 În modalitatea clasica, serverul de Web primeste - de exemplu - o cerere de
tipul:
 GET nume_fisier
 si întoarce fisierul respectiv. Aici nume_fisier este numele unei clase (servlet)
a carei executare întoarce browser-ului un fisier HTML pe care browser-ul îl
afiseaza clientului. Acesta poate completa unele informatii si retrimite o
cerere noua serverului de Web, care prelucreaza informatiile primite si
retrimite rezultatul din nou sub forma unui document HTML. Procesul se
poate repeta de oricâte ori. Un pas al acestui proces poarta numele
de tranzactie. Precizam ca serverul nu pastreaza datele de la o tranzactie la
alta decât daca le stocheaza explicit (de exemplu într-un fisier sau într-o
baza de date).
continuare
 Partea din serverul de Web care asteapta cereri (în cazul nostru cereri de
executare a unui servlet) este numita demon HTTP, deoarece are
caracteristicile unui fir de executare demon. Serverul poate efectua
"simultan" tranzactii cu mai multi clienti, pornind pentru fiecare un fir de
executare.
 Mai mentionam ca schimbul de informatii între server si fiecare client
se face în esenta prin socket-uri, dar la un nivel superior si în mod
transparent pentru utilizator.
 Servlet-urile nu sunt subiectul unor restrictii. Ele creaza documente HTML
dinamice prin succesiunea de tranzactii. Independenta de platforma a
limbajului Java se extinde în mod natural si logic asupra servlet-urilor (spre
deosebire de script-urile CGI care sunt dependente de platforma si care sunt
în plus mai lente).
continuare

Un servlet este o clasă Java care extinde capabilitățile unui server


folosit pentru:
procesarea și stocarea datelor trimise dintr-un formular HTML
oferă conținut dinamic (rezultatele interogărilor DB)
gestionează stările informațiilor transmise, stări ce nu sunt incluse în
protocolul HTTP (umplerea coșului de cumpărături ale unui client on-line)
continuare
 Servlet API history
 Servlet API version Released Platform Important Changes
 Servlet 4.0 September 2017 JavaEE 8 HTTP/
 2 Servlet 3.1 May 2013 JavaEE 7 Non-blocking I/O, HTTP
 protocol upgrade mechanism
 Servlet 3.0 December 2009 JavaEE 6, JavaSE 6 Pluggability, Ease of
 development, Async Servlet, Security, File
Uploading
 Servlet 2.5 September 2005 JavaEE 5, JavaSE 5 Requires JavaSE 5, supports annotation
Servlet 2.4 November 2003 J2EE 1.4, J2SE 1.3 web.xml uses XML Schema
 Servlet 2.3 August 2001 J2EE 1.3, J2SE 1.2 Addition of Filter
 Servlet 2.2 August 1999 J2EE 1.2, J2SE 1.2 Becomes part of J2EE, introduced
 independent web applications in .war files
JavaServer Pages

 JavaServer Pages (JSP) este o tehnologie care ajută la crearea paginilor generate
dinamic prin conversia fișierelor de script în module Java executabile.
 HTTP request către web server.
 .jsp în loc de .html or .htm.
 Serverul web server este un server Java
 identifică și tratează Java servlets.
 serverul Web recunoaște cererea HTTP către pagina JSP -> fwd to JSP
engine.
 JSP Engine încarcă pagina JSP și o convertește la Java servlet.
 JSP Engine compilează servletul într-o clasă Java executabilă -> forwards to
Servlet Engine.
 detecție și recompilare la modificarea fișierelor JSP
 Servlet Engine încarcă clasa servletului și o execută. La executie, servletul
generează output in format HTML
 Servlet Engine transmite outputul HTML către Web Server într-un HTTP
Response.
 Web Server ->
Clasa Servlet
 Un container de servleti transformã cererea HTTP de la client într-un obiect
de tip HTTPServletRequest , transmis la un servlet (sau pagina JSP) care
genereazã un obiect de tip HTTPServletResponse sau transmite cererea unei
alte componente Web. Containerul de servleti transforma acest obiect într-un
raspuns HTTP, transmis la client.

  HTTP Request  HttpServletRequest 


 Client web
Servlet
  HTTP Response  HttpServletResponse 

 Cele mai folosite servere care au si container de servleti sunt Tomcat


(Apache) si Jetty. Ele stau la baza multor servere de aplicatii comerciale sau
gratuite. Un server de aplicatii oferã în plus si alte functii comune aplicatiilor
Web: securitatea si controlul accesului la aplicatii, gestiunea tranzactiilor,
servicii de nume si directoare (JNDI)
continuare
 La primirea unei cereri containerul de servleti realizeazã urmãtoarele actiuni:
 1. Dacã nu existã un obiect servlet în memorie atunci încarcã clasa servlet,
instantiazã clasa (se creeazã un obiect servlet) si apeleazã metoda “init” din
servlet pentru initializãri.
 2. Apeleazã metoda “service” (“doGet’,”doPost”) din servlet transmitând ca
argumente un obiect cerere si un obiect raspuns (obiectul rãspuns va fi
completat de metoda service).
 Functiile unui servlet sunt realizate în metodele service, doGet, doPost s.a.
Aceste metode extrag informatii din obiectul cerere, acceseazã resurse externe
si completeazã rãspunsul cu informatiile obtinute din resurse externe (cum ar fi
baze de date). Parametrii unei cereri apar în sirul de cereri (Query String),
separat de calea la componenta prin ‘?’. Numele si valorile parametrilor unei
cereri sunt preluate de obicei dintr-un formular (transmis de server si completat
de utilizatorul client al aplicatiei) si sunt adãugate la URL prin click pe butonul
Submit dintr-un formular HTML (sau la apãsarea tastei Enter).
continuare
 Clasa HttpServletRequest are metode pentru extragerea parametrilor
dintr-o cerere de cãtre servlet:
 String getParameter (String name) // valoare parametru cu
nume cunoscut
 Enumeration getParameterNames() // iterator pe lista cu
numele tuturor parametrilor din cerere

 Exemplu de extragere a parametrului cu numele “user” dintr-o cerere


de forma:
 http://localhost:8080/hello?user=me
 out.print (“<h1>Hello “);
 out.print (request.getParameter(“user”));
 out.println (“</h1>”);

continuare
 Un exemplu simplu de servlet care afiseazã ca rãspuns un mesaj de salut:
 import java.io.*;
 import javax.servlet.*;
 import javax.servlet.http.*;
 public class HelloServlet extends HttpServlet {
 public void doGet(HttpServletRequest request, HttpServletResponse response) throws
 ServletException, IOException {
 response.setContentType("text/html");
 PrintWriter out = response.getWriter();
 out.println (“ <html>“);
 out.println (“<body> “);
 out.println (“<h1>Hello World! </h1> “);
 out.println (“</body>“);
 out.println (“</html>“);

continuare

 Mai multi servleti dintr-o aplicatie pot folosi date (atribute) din patru
obiecte comune, numite “Scope Objects”:
 Web Context : accesibil tuturor componentelor dintr-un context
(aplicatie)
 Session: accesibil componentelor dintr-o sesiune client
 Request: accesibil componentelor care trateazã o cerere
 Page: accesibil paginii JSP care a creat obiectul
 Intr-o schemã simplã MVC un servlet are rolul de “controller”. De
fapt aplicatiile reale contin mai multi servleti, fiecare “serveste” o
paginã diferitã din aplicatie. Cererile de la clienti sunt primite de un
servlet cu rol de dispecer, care selecteazã un alt servlet din aplicatie
în functie de parametrii cererii HTTP.
Programare in retea

10/24/2019 Curs 13 1
Programare in retea
1.1 Folosirea URL-urilor
– URL (Uniform Resource Locator) reprezinta o referinta
(adresa) a unei resurse de pe Internet
– Structura unui URL: hostname, numele fisierului,
numarul portului (optional) si numele resursei (optional)

http://java.sun.com
Protocol Numele resursei

– Accesarea unui URL se poate face prin intermediul unui


obiect Java din pachetul java.net
Programare in retea
1.1 Folosirea URL-urilor
import java.net.*;
import java.io.*;
public class ParseURL {
public static void main(String[] args) throws Exception {
URL aURL = new URL("http://java.sun.com:80/docs/books/"
+ "tutorial/index.html#DOWNLOADING");
System.out.println("protocol = " +
aURL.getProtocol()); System.out.println("host = " +
aURL.getHost()); System.out.println("filename = " +
aURL.getFile()); System.out.println("port = " +
aURL.getPort()); System.out.println("ref = " +
aURL.getRef());
}
}

Rezultat:
protocol = http
host = java.sun.com
filename = /docs/books/tutorial/index.html
port = 80
ref = DOWNLOADING
Programare in retea
1.2 Connectarea la o resursa web
– Accesarea unei resurse se face prin intermediul obiectului URL
– Metoda openStream intoarce un obiect java.io.InputStream care se
poate accesa ca orice alt flux de intrare

import java.net.*;
import java.io.*;

public class ReadURL {


public static void main(String[] args) throws Exception {
URL osu = new URL("http://www.upm.ro/");
BufferedReader in = new BufferedReader(
new
InputStreamReader(osu.openStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
}
}
Programare in retea
1.2 Connectarea la o resursa web
– O alta metoda a obiectului URL este openConnection care intoarce
un obiect de tip URLConnection – o conexiune catre resursa
accesata
– URLConnection permite atat citirea cat si scrierea in cadrul resursei

try {
URL osu = new URL("http://www.upm.ro/");
URLConnection osuConnection = osu.openConnection();
} catch (MalformedURLException e) { // new URL() failed
. . .
} catch (IOException e) {
. . .
}
Programare in retea
1.4 Programarea serverului
– Pasi necesari:
1. Se creaza un obiect de tip ServerSocket:
ServerSocket server=new ServerSocket(port,queueLength);

2. Serverul va incepe sa asculte mesaje:


Socket connection = server.accept();
3. Se initializeaza obicte de tip OutputStream si InputStream care
permit serverului sa comunice cu clientul:
InputStream input = connection.getInputStream();
OutputStream output = connection.getOutputStream();

4. Faza de procesare: clientul si serverul comunica prin


intermediul obiectelor de tip InputStream si OutputStream
5. Dupa ce comunicarea se incheie, serverul inchide conexiunea
prin apelarea metodei close() la nivelul socketului si pentru
fluxurile corespunzatoare
Programare in retea
1.3 Socket-uri
– Pentru unele aplicatii este nevoie de stabilirea unui canal de
comunicatie low-level, ca in cazul unei aplicatii de tip client-server.
– Un socket (soclu) este o abstractiune software folosita pentru a
reprezenta fiecare din cele doua "capete" ale unei conexiuni intre
doua procese ce ruleaza intr-o retea. Fiecare socket este atasat unui
port astfel incat sa poata identifica unic programul caruia ii sunt
destinate datele.
– Pentru a se conecta, atat clientul cat si serverul au nevoie de cate
un socket pentru scriere, respectiv pentru citire.
– Socket-urile sunt de doua tipuri:
– TCP (Transport Control Protocol), implementate de clasele
Socket si ServerSocket
– UDP (User Datagram Protocol), implementate de clasa
DatagramSocket
– Aceste clase se gasesc in pachetul java.net.
Programare in retea
1.5 Programarea clientului
– Pasi necesari:
1. Se creaza un obiect de tip Socket:
Socket connection = new Socket (serverAddress, port);
2. Se initializeaza obicte de tip OutputStream si InputStream care
permit serverului sa comunice cu serverul
3. Faza de procesare: clientul si serverul comunica prin
intermediul obiectelor de tip InputStream si OutputStream
4. Dupa ce comunicarea se incheie, clientul inchide conexiunea
Programare in retea
1.6 Aplicatie client-server
import java.lang.*;
import java.io.*;
import java.net.*;

class Server {
public static void main(String args[]) {
String data = "Mesaj!";
try {
ServerSocket server_socket = new ServerSocket(1234);
System.out.println("Pornesc...");

Socket socket = server_socket.accept();

System.out.print("Sunt functional!\n");
PrintWriter outToClient = new
PrintWriter(socket.getOutputStream(), true);

System.out.print("Trimit mesaj: " + data + "\n");


outToClient.print(data);

outToClient.close();
socket.close();
server_socket.close();
}
catch(Exception e) {
System.out.print("Oops! Nu a functionat!\n");
}
}
}
Programare in retea
1.6 Aplicatie client-server
import java.lang.*;
import java.io.*;
import java.net.*;

class Client {
public static void main(String args[]) {
try {
Socket socket = new Socket("localhost", 1234);

BufferedReader inFromServer = new BufferedReader(new


InputStreamReader(socket.getInputStream()));

System.out.print("Primesc mesaj: ");


while (!inFromServer.ready()) {}

System.out.println(inFromServer.readLine());

inFromServer.close();
}
catch(Exception e) {
System.out.print(" Oops! Nu a functionat!\n");
}
}
}
Programare in retea
1.7 Datagrame
– Protocolul UDP furnizeaza o alta metoda de comunicare
in retea, prin intermediul datagramelor.
– In acest model clientul trimite un pachet cu cererea
catre server, acesta primeste pachetul si returneaza
raspunsul tot prin intermediul unui pachet.
– Clasa DatagramSockets se foloseste pentru realizarea
conexiunii
Programare in retea
1.7 Datagrame
import java.net.*;
import java.io.*;
public class DatagramServer {
public static final int PORT = 8200;
private DatagramSocket socket = null;
DatagramPacket cerere, raspuns = null;
public DatagramServer() throws IOException {
Socket = new DatagramSocket(PORT);
try {
while (true) {
//Declara pachetul in care va fi receptionata cererea
byte[] buf = new byte[256];
cerere = new DatagramPacket(buf, buf.length);
//Astepta aparitia unui pachet cu cererea
socket.receive(cerere);
//Afla adresa si portul de la care vine cererea
InetAddress adresa = cerere.getAddress();
int port = cerere.getPort();
Programare in retea
1.7 Datagrame
//Construieste raspunsul
buf = ("Hello " + new String(cerere.getData())).getBytes();
//Trimite un pachet cu raspunsul catre client
raspuns = new DatagramPacket(buf, buf.length, adresa, port);
socket.send(raspuns);
}
} finally {
socket.close();
}
}

public static void main(String[] args) throws IOException {


new DatagramServer();
}
}
Programare in retea
1.7 Datagrame
import java.net.*;
import java.io.*;
public class DatagramClient {
public static void main(String[] args) throws IOException {
//adresa IP si portul la care ruleaza serverul
InetAddress address = InetAddress.getByName("127.0.0.1");
int port=8200;
DatagramSocket socket = null;
DatagramPacket packet = null;
byte buf[];
try {
//Construieste un socket pentru comunicare
socket = new DatagramSocket();
//Construieste si trimite pachetul cu cerere catre server
buf = "Duke".getBytes();
packet = new DatagramPacket(buf, buf.length, address, port);
socket.send(packet);
Programare in retea
1.7 Datagrame
//Asteapta pachetul cu raspunsul de la server
buf = new byte[256];
packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);

//Afiseaza raspunsul
System.out.println(new String(packet.getData()));

} finally {
socket.close();
}
}
}
Gruparea firelor de execuție pune la dispoziție
un mecanism pentru manipularea acestora ca un
obiect, și nu individual.
Gruparea firelor de execuție se realizează prin
intermediul clasei ThreadGroup.
Fiecare fir de execuție Java este membru al unui
grup, indiferent dacă specificăm explicit sau nu acest
lucru.
La pornirea unui program Java se creează
automat un obiect de tip ThreadGroup cu numele
main, care va reprezenta grupul tuturor firelor de
execuție create direct din program și care nu au fost
atașate explicit altui grup.
Afilierea unui fir la un anumit grup se
realizează la crearea sa și devine permanentă, nu se
poate muta un fir dintr-un grup în altul, după ce
acesta a fost creat.
Dacă se crează un fir și nu se specifică din ce
grup face parte, el va fi plasat automat în același grup
cu firul de execuțe care l-a creat.
Putem să ignorăm complet plasarea firelor de
execuție în grupuri . Atunci sistemul le va aduna pe
toate în grupul main.
Există situații când gruparea firelor de execuție
poate ușura substanțial manevrarea lor. Putem să
pornim sau să suspendăm toate firele dintr-un grup
cu un singur apel de metodă.
Crearea unui fir de execuție și plasarea lui într-un
grup specificat se realizează prin următorii
constructori ai clasei Thread:
public Thread(ThreadGroup group, Runnable target)
public Thread(ThreadGroup group, String name)
public Thread(ThreadGroup group, Runnable target,
String name)
Fiecare din acești costructori creează un fir de
execuție, îl inițializează și îl plasează într-un grup
specificat ca argument.
Pentru a afla cărui grup aparține un anumit fir de
execuție putem folosi metoda getThreadGroup() a
clasei Thread.
Un grup poate avea ca părinte un alt grup, ceea
ce înseamnă că firele de execuție pot fi plasate într-o
ierarhie de grupuri, în care rădăcina este grupul
implicit main.
Pentru a crea un grup se folosește cintacsa:
ThreadGroup grup1 = new ThreadGroup(„Nume1");
Pentru a crea un grup inclus în alt grup folosim
cintacsa:
ThreadGroup grup2 = new ThreadGroup(grup1,
„Nume2");
Nu toate metodele clasei Thread pot fi utilidate
asupra firelor de execuție din grup.
public class TestAccess
{ public static void main(String[] args)
{ ThreadGroup
x = new ThreadGroup("x"),
y = new ThreadGroup(x, "y"),
z = new ThreadGroup(y, "z");
Thread
one = new TestThread1(x, "one"),
two = new TestThread2(z, "two");
}}
class TestThread1 extends Thread
{ private int i;
TestThread1(ThreadGroup g, String name)
{ super(g, name); }
void f()
{ i++;
System.out.println(getName() + " f()"); }}
class TestThread2 extends TestThread1
{ TestThread2(ThreadGroup g, String name)
{ super(g, name);
start(); }
public void run()
{ ThreadGroup g =
getThreadGroup().getParent().getParent();
g.list();
Thread[] gAll = new Thread[g.activeCount()];
g.enumerate(gAll);
for(int i = 0; i < gAll.length; i++)
{ gAll[i].setPriority(Thread.MIN_PRIORITY);
((TestThread1)gAll[i]).f(); }
g.list(); }}
java.lang.ThreadGroup[name=x,maxpri=10]
Thread[one,5,x]
java.lang.ThreadGroup[name=y,maxpri=10]
java.lang.ThreadGroup[name=z,maxpri=10]
Thread[two,5,z]
one f()
two f() java.lang.ThreadGroup[name=x,maxpri=10]
Thread[one,1,x]
java.lang.ThreadGroup[name=y,maxpri=10]
java.lang.ThreadGroup[name=z,maxpri=10]
Thread[two,1,z]
Fiecare fir de executie Java primește la crearea sa o
anumită prioritate. O prioritate este de fapt un numar
întreg cu valori cuprinse între 1 și 10. Implicit prioritatea
unui fir de execuție nou creat are valoarea 5. Pot fi
utilizate trei constante care sunt definite în clasa Thread:
public static final int MIN_PRIORITY –
prioritatea minimă 1
public static final int NORM_PRIORITY –
prioritatea implicită 5
public static final int MAX_PRIORITY –
prioritatea maximă 10
Schimbarea ulterioară a prioritații unui fir de
execuție se realizează cu metoda setPriority() a clasei
Thread.
Grupul cu fire de execuție implicit la creare
primește prioritatea 10. Dar poate fi modificată de
la 1 pînă la 10.
Proipitatea grupului poate fi modificată cu
metoda setMaxPriority() a clasei ThreadGroup.
La modificarea priorității grupului sau a firului
de execuție există unele restricții.
public class SPriority extends Thread
{private int countD=5;
private volatile double d=0;
public SPriority(int priority)
{setPriority(priority);
start();}
public String toString
{return super.toString() + “:” + countD;}
public void run()
{while(true)
for(int i=0; i<100000; i++)
d=d+(Math.PI+Math.E)/(double)i;
System.out.println(this)
If(--countD==0) return;}}
public static void main(String[]args)
{new SPriority(Thread.MAX_PRIORITY);
for(int i=0; i<5; i++)
new SPriority (Thread.MIN_PRIORITY);}}
Thread[Thread-1.10.main]:5 Thread[Thread-4.1.main]:4
Thread[Thread-1.10.main]:4 Thread[Thread-5.1.main]:4
Thread[Thread-1.10.main]:3 Thread[Thread-6.1.main]:4
Thread[Thread-1.10.main]:2 Thread[Thread-3.1.main]:3
Thread[Thread-1.10.main]:1 Thread[Thread-4.1.main]:3
Thread[Thread-2.1.main]:5 Thread[Thread-5.1.main]:3
Thread[Thread-2.1.main]:4 Thread[Thread-6.1.main]:3
Thread[Thread-2.1.main]:3 Thread[Thread-3.1.main]:2
Thread[Thread-2.1.main]:2 Thread[Thread-4.1.main]:2
Thread[Thread-2.1.main]:1 Thread[Thread-5.1.main]:2
Thread[Thread-3.1.main]:5 Thread[Thread-6.1.main]:2
Thread[Thread-4.1.main]:5 Thread[Thread-4.1.main]:1
Thread[Thread-5.1.main]:5 Thread[Thread-3.1.main]:1
Thread[Thread-6.1.main]:5 Thread[Thread-6.1.main]:1
Thread[Thread-3.1.main]:4 Thread[Thread-5.1.main]:1
public class ThreadGroup1
{ public static void main(String[] args)
{ ThreadGroup sys =
Thread.currentThread().getThreadGroup();
sys.list();
// (1)
sys.setMaxPriority(Thread.MAX_PRIORITY - 1);
Thread curr = Thread.currentThread();
curr.setPriority(curr.getPriority() + 1);
sys.list();
 (1)ThreadGroup[name=system,maxpri=10]
 Thread[main,5,system]
 (2) ThreadGroup[name=system,maxpri=9]
 Thread[main,6,system]
 (1) Numele grupului de bază este system,
numele procesului principal este main și
aparține grupului system
 (2) Implicit prioritatea grupului este 10 și
micșorăm la 9. Implicit prioritatea thread-ului
este 5 și mărim la 6.
ThreadGroup g1 = new ThreadGroup("g1");

g1.setMaxPriority(Thread.MAX_PRIORITY);

Thread t = new Thread(g1, "A");

t.setPriority(Thread.MAX_PRIORITY);

g1.list();
// (3)
(3) ThreadGroup[name=g1,maxpri=9]
Thread[A,9,g1]

Se crează grupul g1 care automat este inclusă în


grupul de sistemă. Se crează thread-ul A inclus în
grupul g1.
Nu se poate de modificat prioritatea grupului mai
mare ca proiritatea grupului căruia îi aparține.
Nu se pote de modificat ptioritatea thread-ului mai
mare ca pioritatea grupului fr sistemă.
g1.setMaxPriority(Thread.MAX_PRIORITY - 2);

g1.setMaxPriority(Thread.MAX_PRIORITY);

g1.list();
// (4)
(4) ThreadGroup[name=g1,maxpri=8]
Thread[A,9,g1]

Prioritatea grupului se poate numai de micșorat și


nu poate fi mărit. Prioritatea thread-ului rămîne
aceiaș.
t = new Thread(g1, "B");
t.setPriority(Thread.MAX_PRIORITY);
g1.list();
// (5)
(5) ThreadGroup[name=g1,maxpri=8]
Thread[A,9,g1]
Thread[B,8,g1]
Implicit prioritatea thread-ului creat este 6 ca
proiritatea procesului de sistemă. Dar la
modificare nu pote fi mai mare ca prioritatea
grupului căruia îi aparține.
g1.setMaxPriority(Thread.MIN_PRIORITY + 2);
t = new Thread(g1, "C");
g1.list();
// (6)
(6) ThreadGroup[name=g1,maxpri=3]
Thread[A,9,g1]
Thread[B,8,g1]
Thread[C,6,g1]
Dacă prioritatea grupului este mai mică ca
prioritatea procesului de sistemă, atunci
prioritatea thread-ului creat în grupul g1 va
primi prioritatea mai mare ca prioritatea
grupului egală cu prioritatea procesului de
sistemă.
// (6)
t.setPriority(t.getPriority() -1);
g1.list();
ThreadGroup[name=g1,maxpri=3]
Thread[A,9,g1]
Thread[B,8,g1]
Thread[C,3,g1]

Dacă încercăm să modificăm priotitatea


threa-ului cu valooare mai mare ca prioritatea
grupului atunci prioritatea thread-ului va fi ca
prioritarea grupului căruia îi aparține.
ThreadGroup g2 = new ThreadGroup(g1, "g2");
g2.list();
// (8)
g2.setMaxPriority(Thread.MAX_PRIORITY);
g2.list();
// (9)
(8) ThreadGroup[name=g2,maxpri=3]
(9) ThreadGroup[name=g2,maxpri=3]

La crearea unui grup inclus în alt grup


prioritatea implicit devine egală cu prioritatea
grupului părinte. Dacă încercăm să marim
prioritatea, nu reușim.
for (int i = 0; i < 5; i++) new Thread(g2,
Integer.toString(i));
sys.list();
// (10)
(10)ThreadGroup[name=system,maxpri=9]
Thread[main,6,system]
ThreadGroup[name=g1,maxpri=3]
Thread[A,9,g1]
Thread[B,8,g1]
Thread[C,3,g1]
ThreadGroup[name=g2,maxpri=3]
Thread[0,6,g2]
Thread[1,6,g2]
Thread[2,6,g2]
Thread[3,6,g2]
Thread[4,6,g2]
Thread-urile au primir prioritatea procesului.
 Caracteristici:
Sunt fire speciale similare cu procesele demoni.
 Realizeaza anumite activitati in fundal
(background)
 Se distrug automat la terminarea celorlaltor fire de
executie și finalizarea programului.
 Au prioritate de executie redusa, fiind planificate
la CPU cand acesta nu ruleaza alte fire
 Firul poate fi transformat in fir demon prin apelul
metodei setDaemon().
class SDaemons extends Thread
{ public SDaemons()
{setDaemon(true);
//start();
}
public void run()
{while(true)
{try
{ System.out.println(this);
sleep(100);}
catch (InterruptedException e)
{throw new RuntimeException(e);}
}}
public static void main (String[]args)
{for(int i=0; i<10; i++)
new SDaemons().start();}}
Thread[Thread-0,5,main]
Thread[Thread-1,5,main]
Thread[Thread-2,5,main]
Thread[Thread-3,5,main]
Thread[Thread-5,5,main]
Thread[Thread-7,5,main]
Thread[Thread-9,5,main]
Thread[Thread-4,5,main]
Thread[Thread-6,5,main]
Thread[Thread-8,5,main]
class Daemon extends Thread
{ private static final int SIZE = 10;
private Thread[] t = new Thread[SIZE];
public Daemon()
{ setDaemon(true);
start(); }
public void run()
{ for(int i = 0; i < SIZE; i++)
t[i] = new DaemonSpawn(i);
for(int i = 0; i < SIZE; i++)
System.out.println( "t[" + i + "].isDaemon() = " +
t[i].isDaemon());
while(true) yield(); } }
class DaemonSpawn extends Thread
{ public DaemonSpawn(int i)
{ System.out.println( "DaemonSpawn " + i + " started");
start(); }
public void run()
{ while(true)
yield();
}}
public class Daemons
{ public static void main(String[] args)
{ Thread d = new Daemon();
System.out.println( "d.isDaemon() = " + d.isDaemon());
System.out.println("Press any key");
}}
d.isDaemon() = true t[0].isDaemon() = true
Press any key t[1].isDaemon() = true
DaemonSpawn 0 started t[2].isDaemon() = true
DaemonSpawn 1 started t[3].isDaemon() = true
DaemonSpawn 2 started t[4].isDaemon() = true
DaemonSpawn 3 started t[5].isDaemon() = true
DaemonSpawn 4 started t[6].isDaemon() = true
DaemonSpawn 5 started t[7].isDaemon() = true
DaemonSpawn 6 started t[8].isDaemon() = true
DaemonSpawn 7 started t[9].isDaemon() = true
DaemonSpawn 8 started
DaemonSpawn 9 started
Thread-uri preemtive
și cooperative
Ciclul de viaţă

 1. Starea ”NewThread”
 Obiectul fir de execuție a fost creat dar înca nu a fost
startat.
 Thread fir=new Thread(obiectActiv);
 //fir se gaseste in starea "New Thread„
 Nu are alocate resurse
 Putem apela start
 2. Runnable – Firul se afla in starea in care poate fi
rulat in momentul in care procesorul devine
disponibil.
 Fir.start();
// firul de execuție devine activ
Alocare resurse
Planificare la procesor
Apel run()
 3. Blocked sau not-runnable – Firul de execuție
este blocat si nu poate fi rulat, chiar daca
 procesorul este disponibil.
 Este ”adormit de metoda sleep()
 Activăm metoda wate() așteptînd realizarea unei
condișii
 Este blocat într-o operație de I/O
 4. Dead – Calea normala prin care un fir se termina
este prin ieșirea din metoda run(). Se poate forța
terminarea firului apelând metoda stop()
 dar nu se recomanda folosirea sa, fiind o metoda
“depreciată” in Java2.

 System.exit termină forțat toate firele de execuție


Modurile de rulare a thread-urilor

Sistemele de operare “programează” diferitele


procese pentru a rula în două moduri:

- Preemptiv
- Cooperativ
Sistem preemptiv

În cazul sistemelor preemptive sistemul de operare oferă


fiecărui proces sau fir de execuţie o cuantă de timp pentru
a-şi îndeplini scopul. Sistemele preemptive garantează că
fiecare fir de execuţie va ajunge să ruleze într-o perioadă
de timp dată – altfel spus fiecare fir are rezervate, de
exemplu, cîte 50 milisecunde pentru rulare. Chiar dacă în
acest timp firul de execuţie nu a reuşit să-şi îndeplinească
misiunea, starea lui este salvată şi un alt fir va fi lansat în
execuţie de către sistemul de operare. Acest lucru se
întîmplă pînă cînd toate firele de execuţie reuşesc să
ruleze o dată. Apoi procesul se reia începînd cu primul fir
de execuţie – acesta rulează 50 milisecunde, urmează la
rînd al doilea fir de execuţie care rulează din nou 50
milisecunde şi aşa mai departe.
Sistem cooperativ
 În cazul sistemelor cooperative, fiecare fir de execuţie trebuie
să permită în mod voluntar accesul altor fire la resursele
sistemului. Am subliniat “în mod voluntar” pentru că în acest
caz sistemul de operare nu mai este responsabil pentru
“programarea” diferitelor procese sau fire pentru a rula – este
răspunderea fiecărui fir în parte pentru a permite şi altora să-
şi desfăşoare activitatea. În practică putem întîlni situaţii în
care un fir caparează resursele întregului sistem pînă cînd
termină ceea ce are de făcut fără să mai permită altui fir
dreptul de rulare. Sistemele de multitasking cooperativ sînt
eficiente în cazul aplicaţiilor în timp real.
 O bună parte dintre implementările maşinii virtuale Java
utilizează politica cooperativă. Aceasta înseamnă că fiecare fir
dintr-o aplicaţie Java trebuie să ofere periodic oportunitatea
rulării şi altor fire. Există mai multe posibilităţi pentru
atingerea acestui scop.
Crearea firelor de
execuție
Definiția thread-urilor
 Firele de execuție reprezintă mecanismul prin care pot fi
implementate în cadrul unui program secvențe de cod ce
se execută virtual în paralel.
 Trebuie făcută distincție între fire de execuție și procese.
Deși ambele concepte implică execuția în paralel a unor
secvențe de cod există o serie de deosebiri
fundamentale între procese și fire de execuție. Procesele
sunt entități independente ce se execută independent și
sunt gestionate de către nucleul sistemului de operare.
Firele de execuție sunt secvențe ale unui program
(proces) ce se execută aparent în paralel în cadrul unui
singur proces.
Construirea și startarea thread-urilor

 Java implementează mecanismele necesare pentru a


inițializa și executa un fir de execuție este clasa Thread.
Pentru a construi un fir de execuție trebuie extinsă
 clasa Thread și suprascrisă metoda run() din cadrul
acestea. În cadrul metodei run() se va implementa
secvența de instrucțiuni ce se va executa în momentul în
care un fir de execuție este startat.
 Pentru a lansa în execuție un fir se folosește metoda
start() (moștenită de asemenea din cadrul clasei
Thread). Această metodă este responsabilă cu
inițializarea tuturor mecanismelor necesare pentru a
putea executa un fir de execuție, după care va apela
automat metoda run().
Metodele de creare a thread-urilor

 1. Clasa Thread
 O modalitate de a crea şi lansa in execuţie
fire (de execuţie ) este de a folosi clasa
Thread din pachetul java.lang:
 Public class Thread1extends Thread
 Pentru a crea un fir de execuţie , trebuie
să cream un obiect de tipul Thread:
 Thread fir=new Thread();
 2. Interfața Runnable constituie o
alternativă la extinderea clasei Thread.
 Avantajul constă in primul rând în însusi
faptul că este o interfaţă: o clasă oarecare
poate implementa Runnable şi extinde o
altă clasă (pe când o clasă ce extind
Thread nu mai poate extinde vreo altă
clasă).
 public class Thread11 extends Objects11
implements Runnable
Crearea thread-urilor utilizînd clasa Thread
public class SimpleThread extends Thread {
private int countDown = 5;
private static int threadCount = 0;
private int threadNumber = ++threadCount;
public SimpleThread() {
System.out.println("Making " + threadNumber); }
public void run() {
while(true)
{ System.out.println("Thread " + threadNumber + "(" +
countDown + ")");
if(--countDown == 0) return;
}}
public static void main(String[] args) {
for(int i = 0; i < 5; i++)
new SimpleThread().start();
System.out.println("All Threads Started");
}}
Rezultatul realizării:
Making 1 Thread 5(4)
Making 2 Thread 1(3)
Thread 1(5) Thread 4(3)
Making 3 Thread 2(3)
Thread 2(5) Thread 3(3)
Making 4 Thread 5(3)
Making 5 Thread 1(2)
Thread 4(5) Thread 4(2)
All Threads Started Thread 2(2)
Thread 3(5) Thread 3(2)
Thread 5(5) Thread 5(2)
Thread 1(4) Thread 1(1)
Thread 2(4) Thread 4(1)
Thread 4(4) Thread 2(1)
Thread 3(4) Thread 5(1)
Thread 3(1)
Utilizarea interfeții Runnable
public class ThreadRun impliments Runnable
{ privat int count =5;
public String toString(){
return “#”+Thread.currentThread().getName()+count;
}
public void run(){
while (true) {
System.out.primtln(this);
if (--count==0) return;
}}
public static void main(String[ ]args)
{for(int i=0; i<5; i++)
New Thread(new ThreadRun()).start();
}}
Clasa Thread
Sincronizarea thread-urilor cu yield()
public class SimpleThread1 extends Thread
{
private int countDown = 5;
private static int threadCount = 0;
private int threadNumber = ++threadCount;
public SimpleThread1()
{
System.out.println("Making " + threadNumber); }
public void run()
{
while(true)
{ System.out.println("Thread " + threadNumber + "(" + countDown + ")");
if(--countDown == 0) return;
yield();
}}
public static void main(String[] args)
{
for(int i = 0; i < 5; i++)
new SimpleThread1().start();
System.out.println("All Threads Started");
}}
Sincronizarea thread-urilor cu sleep()
public class SimpleThread extends Thread
{
private int countDown = 5;
private static int threadCount = 0;
private int threadNumber = ++threadCount;
public SimpleThread()
{
System.out.println("Making " + threadNumber); }
public void run()
{
while(true)
{ System.out.println("Thread " + threadNumber + "(" + countDown + ")");
if(--countDown == 0) return;
try{ sleep(100);}
Catch (InterruptedException e)
{
Throw new RuntimeException(e);}
}}
public static void main(String[] args)
{
for(int i = 0; i < 5; i++)
new SimpleThread().start();
System.out.println("All Threads Started");
Metodele clasei Thread
Constructorii
 Crearea unui nou obiect Thread
 public Thread();
 Crearea unui nou obiect Thread cu indicarea obiectului pentru care
va fi activată metoda run().
 public Thread(Runnable target);
 Analogic constructorului precedent, dar se indică ți numele
obiectului Thread
 public Thread(Runnable target, String name);
 Crearea unui nou obiect Thread și se indică numele lui.
 public Thread(String name);
 Crearea unui nou obiect Thread, se indică numele grupului căruia îi
aparâine și obiectul pentru cae va fi activată metoda run().
 public Thread(ThreadGroup group, Runnable target);
 Analogic constructorului precedent, dar se indică ți numele
obiectului Thread
 public Thread(ThreadGroup group, Runnable target, String
name); Crearea unui nou obiect Thread cu indicarea numelui
grupului căruia îi aparâine și numele lui.
 public Thread(ThreadGroup group, String name);
Metodele
 activeCount apreciază numărul de thread-uri active din grupul
căruia îi aparâine
 public static int activeCount();

 currentThread apreciază thread-ul curent activ


 public static Thread currentThread();

 destroy finalifarea forțată a thread-ului


 public void destroy();

 enumerate apreciază toate thread-urile din grupa dată.


 public static int enumerate(Thread tarray[]);

 getName apreciază numele thread-ului.


 public final String getName();

 getPriority apreciază prioritatea curentă a thread-ului


 public final int getPriority();
continuare

 getThreadGroup apreciază grupul căruia îi aparține thread-ul


 public final ThreadGroup getThreadGroup();

 interrupt întrerupe realizarea thread-ului


 public void interrupt();

 Interrupted aptreciază dacă thread-ul este întrerupt


 public static boolean interrupted();

 isAlive apreciază dacă thread-ul se realizează sau nu


 public final boolean isAlive();

 isDaemon apreciază este thread-ul daemon


 public final boolean isDaemon();

 resume restartarea thread-ului temporar oprit


 public final void resume();
continuare
 join așteaptă realizarea complectă a thread-ului sau așteaptă
realizarea thread-ului pe parcursul timpului indicat în milisecunde și
nanosecunde
 public final void join();
 public final void join(long millis);
public final void join(long millis, int nanos);

 run metoda este activată pentru a realiza thread-ul


 public void run();

 setDaemon indică că thread-ul creat va fi daemon


 public final void setDaemon(boolean on);

 setName atribue nume thread-ului


 public final void setName(String name);

 yield oprește temporar thread-ul activ a transmite comanda altui


thread
 public static void yield();
continuarе
 setPriority instalarea priorității
 public final void setPriority(int newPriority);

 sleep ”adormirea” thread-ului pe timpul indicat în milisecunde și


nanosecunde
 public static void sleep(long millis);
 public static void sleep(long millis, int nanos);

 start activarea thread-ului


 public void start();

 stop dezactivarea finală a thread-urilor


 public final void stop();

 suspend dezactivarea temporară a thread-ului


 public final void suspend();