Documente Academic
Documente Profesional
Documente Cultură
Lab. 1
Lab. 2
Lab. 3
Lab. 4
1
1
10
6
3
2
9
2
8
4
3
6
3
4
8
4
2
1
7
5
5
4
7
5
6
6
5
6
10
7
7
7
4
2
9
8
8
9
3
1
9
10
5
9
2
10
3
8
1
10
PARTEA 1
1.1 Fire de execuie
1.1.1 Ce este un fir de execuie ?
Firele de execuie fac trecerea de la programarea
secvenial la programarea concurent Un program secvenial
reprezint modelul clasic de program: are un nceput, o secven de
execuie a instruciunilor sale i un sfrit. Cu alte cuvinte, la un
moment dat programul are un singur punct de execuie. Un
program aflat n execuie se numeste proces. Un sistem de operare
monotasking (MS-DOS) nu este capabil sa execute dect un singur
proces la un moment dat, n timp ce un sistem de operare
multitasking (UNIX, Windows) poate rula oricte procese n
acelai timp (concurent), alocnd periodic cuante din timpul de
lucru al CPU fiecrui proces. Am reamintit acest lucru deoarece
noiunea de fir de execuie nu are sens dect n cadrul unui sistem
de operare multitasking. Un fir de execuie este similar unui proces
secvenial n sensul c are un nceput, o secven de execuie i un
sfrit. Diferena ntre un fir de execuie i un proces const n
faptul c un fir de execuie nu poate rula independent, ci trebuie s
ruleze n cadrul unui proces.
a)
b)
Fig.1 Fire de execuie n cadrul
unui program
Program cu un fir de execuie;
Program cu mai multe fire de execuie
11
clasei Thread
determin crearea unui fir de execuie care la lansarea sa va cuta
n clasa noastr metoda run i o va executa. Acest constructor
accept ca argument orice instan a unei clase "Runnable". Asadar,
metoda run nu trebuie apelat explicit, acest lucru realizndu-se
automat la apelul metodei start().
Apelul explicit al metodei run nu va furniza nici o eroare, ns
aceasta va fi executat ca orice alt metod, deci nu ntr-un fir de
execuie. Sa rescriem acum exemplul anterior (afiarea numerelor
12
Varianta 2
Crearea firului de execuie se realizeaz n afara clasei Counter:
class Counter implements Runnable {
private int from, to, step;
13
}
public class TestThread2 {
public static void main(String args[]) {
Counter cnt1, cnt2;
cnt1 = new Counter(0, 100, 5);
cnt2 = new Counter(100, 200, 10);
new Thread( cnt1 ).start();
//lansez primul fir de execuie
new Thread( cnt2 ).start();
//lansez al doilea fir de execuie
}
}
14
2. Starea "Runnable"
Dup apelul metodei start un fir de execuie va trece n starea
"Runnable", adic se gsete n execuie.
counterThread.start();
//counterThread se gsete n starea Runnable
Metoda start realizeaz urmatoarele operaiuni necesare
rulrii
firului de execuie: aloc resursele sistem necesare, planific firul
de execuie la CPU pentru a fi lansat, apeleaz metoda run a
obiectului reprezentat de firul de execuie.
15
4. Starea "Dead"
Este starea n care ajunge un fir de execuie la terminarea sa. Un fir
de execuie nu poate fi oprit din program printr-o anumit metod,
ci trebuie s se termine n mod natural la terminarea metodei run
pe care o execut. Terminarea unui fir de execuie folosind o
variabil de terminare:
import java.io.*;
16
19
20
21
(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]
Starting all threads:
All threads started
5. Probleme propuse:
Realizarea lucrrii de laborator nr. 1 const din 2 probleme.Prima
problem ine de crearea i executarea firelor de execuie. A doua
problem se refer la gruparea i enumerarea firelor de execuie.
Problema nr.1:
22
Tabelul 1
Condiii la problema nr. 1 l/lab nr. 1
1
2
3
4
5
6
7
8
Condiie 1
Condiie 2
23
9
10
Problema nr. 2:
De
Tabelul 2
Formula structurii, compus din fire i
grupuri de fire
1
2
3
4
5
6
7
8
9
10
25
26
sleep((int)(Math.random() * 100));
} catch (InterruptedException e) { }
}
}
class Consumator extends Thread {
private Buffer buffer;
public Consumator(Buffer b) {
buffer = b;
}
public void run() {
int value = 0;
for (int i = 0; i < 10; i++) {
value = buffer.get();
System.out.println("Consumatorul a
primit:\t" + value);
}
}
}
//Clasa principal
public class TestSincronizare1 {
public static void main(String[] args) {
Buffer b = new Buffer();
Producator p1 = new Producator(b);
Consumator c1 = new Consumator(b);
p1.start();
c1.start();
}
}
27
a
a
a
a
a
a
primit:
primit:
pus:
primit:
primit:
primit:
-1
-1
0
0
0
0
Producatorul
Producatorul
Producatorul
Producatorul
Producatorul
Producatorul
Producatorul
Producatorul
Producatorul
a
a
a
a
a
a
a
a
a
pus:
pus:
pus:
pus:
pus:
pus:
pus:
pus:
pus:
1
2
3
4
5
6
7
8
9
28
2.
29
Consumatorul
Producatorul
Consumatorul
. . .
Producatorul
a primit: 0
a pus:
1
a primit: 1
a pus:
30
Dup
elibereaz
monitorul asociat obiectului respectiv i ateapt ca una din
urmtoarele condiii s fie ndeplinit:
un alt fir de execuie informeaz pe cei care "ateapt" la un
anumit monitor s se trezeasc; acest lucru se realizeaz
printr-un apel al metodei notifyAll sau notify.
perioada de ateptare specificat a expirat.
Metoda
wait
poate
InterruptedException,
produce
excepii
de
tipul
atunci cnd firul de execuie care
asteapt (este deci n starea Not Runnable) este ntrerupt din
ateptare i trecut forat n starea Runnable, dei condiia ateptat
nu era nc ndeplinit. Metoda notifyAll informeaz toate firele
de execuie, care sunt n ateptare la monitorul obiectului curent,
ndeplinirea condiiei pe care o ateptau. Metoda notify
informeaz doar un singur fir de execuie. Iat variantele corecte
ale metodelor get i put:
public synchronized int get() {
while (!available) {
try {
wait();
//ateapt productorul s pun o valoare
} catch (InterruptedException e) { }
}
available = false;
notifyAll();
return number;
}
public synchronized void put(int number) {
33
while (available) {
try {
wait();
//ateapt consumatorul s preia valoarea
} catch (InterruptedException e) { }
}
this.number = number;
available = true;
notifyAll();
}}
2.2.3 Bariere
n aplicaiile multithreading este necesar ca anumite thread-uri s
se sincronizeze la un anumit punct. Un exemplu este calculul
paralel n faza, n care toate thread-urile trebuie s-i termine faza
de execuie nainte de a trece toate odat la faza urmtoare. O
barier este un mecanism folosit pentru a sincroniza mai multe
thread-uri. Un thread care ntlnete o barier intr automat n
wait(). Cnd ultimul thread "ajunge" la barier, semnaleaz
(notify()) celorlalte thread-uri, care sunt n ateptare, rezultnd o
"trecere" n grup a barierei. Iat un exemplu n acest sens:
import java.util.*;
class Barrier { // Clasa Barrier sincronizeaz toi
//participanii private
int ParticipatingThreads;
private int WaitingAtBarrier;
public Barrier(int num){ //Constructorul
ParticipatingThreads = num;
WaitingAtBarrier=0;
}
public synchronized void Reached(){
//Metoda bariera
WaitingAtBarrier++;
if(ParticipatingThreads != WaitingAtBarrier){
//Inseamna ca thread-ul nu este ultimul
34
try {
}
}
37
System.out.println("Consumer #" +
this.number + " got: " + value);
}
}
public class ProducerConsumerTest {
public static void main(String[] args) {
CubbyHole c = new CubbyHole();
Producer p1 = new Producer(c, 1);
Consumer c1 = new Consumer(c, 1);
p1.start();
c1.start();
}
}
5. Probleme propuse:
X productori genereaz aleatoriu F obiecte care sunt
consumate de Y consumatori. De afiat informaia despre
producerea i consumarea obiectelor, mesajele despre cazurile
cnd depozitul e gol sau plin. Toate operaiile se efectueaz
pn cnd fiecare consumator este ndestulat cu Z obiecte.
Dimensiunea depozitului este D. Valorile se iau din tabelul 3
Tabelul 3
Date iniiale pentru problem la l/lab nr. 3
Nr.
1
2
3
4
5
6
7
8
9
2
3
4
3
2
2
3
4
5
3
4
3
2
5
4
3
2
2
11
2
3
12
3
4
5
4
3
8
5
10
11
12
7
6
5
4
38
Tip Obiecte
Numere pare
Numere impare
Vocale
Consoane
Numere pare
Numere impare
Vocale
Consoane
Numere pare
3
3
5
2
10
Numere impare
* fiecare productor poate produce cte 2 obiecte de fiecare
dat
PARTEA 3
3.1 Applet-uri
3.1.1 Ce este un applet ?
Definiie
Un applet reprezint o suprafa de afiare (container) ce
poate fi inclus ntr-o pagin Web i gestionat printr-un
program Java. Un astfel de program se mai numete
miniaplicaie sau, prin abuz de limbaj, applet.
Codul unui applet poate fi format din una sau mai multe clase. Una
dintre acestea este principal i extinde clasa Applet, fiind clasa ce
trebuie specificat n documentul HTML ce descrie pagina de Web
n care dorim s includem appletul.
Diferena fundamental dintre un applet i o aplicaie const n
faptul c un applet nu poate fi executat independent, ci va fi
executat de browserul n care este ncrcat pagina Web, ce conine
appletul respectiv. O aplicaie independent este executat prin
apelul interpretorului java, avnd ca parametru numele clasei
principale a aplicaiei, clasa principal fiind cea, care conine
metoda main. Ciclul de via al unui applet este complet diferit,
fiind dictat de evenimentele generate de ctre browser la
vizualizarea documentului HTML, ce contine appletul. Pachetul
care ofer suport pentru creearea de appleturi este java.applet.
3.1.2 Crearea unui applet
39
40
Execuia (vizualizarea)
Pentru a vizualiza acest applet trebuie s crem un document
HTML, s-i spunem demo.html, n care s specificm cel puin
urmatoarele informaii:
clasa ce contine codul appletului;
limea i nlimea suprafeei alocate pe pagina Web
<HTML>
<HEAD><TITLE> Un applet simplu </TITLE>
</HEAD>
<APPLET CODE="AppletSimplu.class" WIDTH=100
HEIGHT=50></APPLET>
</HTML>
41
}
public void paint(Graphics g) {
}
}
42
44
java.awt.Graphics;
java.awt.Font;
java.awt.Image;
java.awt.Rectangle;
46
resize(w,h);
s=getParameter("text");
if(s==null)
s="The Java ScrollText at work.";
separated =new char[s.length()];
s.getChars(0,s.length(),separated, 0);
offscreenImage=createImage(w,h);
offscreenGraphics=offscreenImage.getGraphics();
offscreenGraphics.setFont(new
Font("TimesRoman",Font.BOLD,h-2));
}
public void start(){
if(killme==null){
killme=new Thread(this);
killme.start();
}
}
public void stop(){
killme=null;
}
public void run(){
while(killme!=null){
try{
Thread.sleep(speed);
}catch(InterruptedException w){}
scroll();
}
killme=null;
}
synchronized void scroll(){
dist--;
if(dist+((s.length()+1)*(h*5/11))==0)
dist=w;
repaint();
}
public void paint(Graphics g){
Rectangle r=bounds();
47
offscreenGraphics.clearRect(0,0,r.width,
r.height);
offscreenGraphics.drawChars(separated,0,s.length(),
dist,4*h/5);
g.drawImage(offscreenImage,0,0,this);
}
public void update(Graphics g){
paint(g);
}
public boolean mouseDown(java.awt.Event evt, int
x, int y){
if(threadSuspended){
killme.resume();
}else{
killme.suspend();
}
threadSuspended=!threadSuspended;
return true;
}
}
48
5. Probleme propuse:
De scris un program pentru realizarea unui applet ce va utiliza
firele de execuie pentru realizarea:
1.
Ceas, ce poate fi setat i restartat prn click ( prefaa
unei emisiuni TV);
2.
Cronometru, cu butoanele start/stop i reset;
3.
Generare de figuri geometrice ce se mic, ce pot fi
create sau distruse apsnd pe butonul ce corespunde
figurii;
4.
Joc de calculator tetris cu 2 figuri de tipul tetris
utiliznd tastatura, n care pot fi 2 participani;
5.
Componenta text ce i schimba umbrele n
dependen de micarea sursei de lumin;
6.
Image loader, applet ce afieaz un ir de imagini, n
timp ce se poate de scris text n TextArea;
7.
Spot publicitar, ce poate fi ntrerupt i repornit, ce
caracterizeaz FCIM;
8.
Spot publicitar ce poate fi ntrerupt i repornit, ce
caracterizeaz Catedra Calculatoare;
9.
Spot publicitar ce poate fi ntrerupt i repornit, ce
caracterizeaz Cursul Java;
10.
Component, ce poate fi intrerupt i repornit, ce
reprezint micarea planetelor n sistemul solar, ca o parte
a unui applet, ce ar permite listarea imaginilor n acelai
timp de ctre utilizator.
49
PARTEA 4
4.1 Ce sunt fluxurile?
Adeseori programele necesit citirea unor informaii care se gsesc
pe o surs extern sau trimiterea unor informaii ctre o destinaie
extern. Informaia se poate gsi oriunde: ntr-un fiier pe disc, n
reea, n memorie sau n alt program i poate fi de orice tip: date
primitive, obiecte, imagini, sunete, etc. Pentru a aduce informaii
dintr-un mediu extern, un progam Java trebuie s deschid un
canal de comunicaie (flux) ctre sursa informaiilor (fiier,
memorie, socket, etc) i s citeasc serial informaiile respective,
cum e artat n fig.5.
50
Scrierea
51
Reader
InputStream
int read()
int read()
int read(char buf[])
int read(byte buf[])
int read(char buf[], int int read(byte buf[], int
offset,int length)
offset,int length)
write()
write(char buf[])
write(char buf[],
offset,int length)
OutputStream
int write()
int write(byte buf[])
int write(byte buf[], int
offset,int length)
52
53
54
55
out.close();
}
Obs: metoda main arunca excepii IOException
care este superclasa pentru
FileNotFoundException. Aceste excepii nu vor fi
"prinse", dect de nterpretor i va fi afiat
un mesaj de eroare la apariia lor.
56
57
TT_EOL TT_NUMBER
TT_WORD
nval
sval
ttype
-
58
60
61
Clasa
Java
care
reprezint
noiunea
de
adres
IP este
InetAddress.
62
http://java.sun.com,
http://mail.md.
o
o
63
Conectarea
la
un
openConnection().
URL
se
realizeaz
prin
metoda
4.2.7 Socket-uri
Definiie
Un socket (soclu) este o abstraciune software folosit
pentru a reprezenta fiecare din cele dou "capete" ale unei
conexiuni ntre dou procese ce ruleaz ntr-o reea.
Fiecare socket este ataat unui port astfel, nct s poat
identifica unic programul cruia i sunt destinate datele.
64
ServerSocket
o
65
66
try {
//Asteapta un client
clientSocket = serverSocket.accept();
//Execut solicitarea clientului ntr-un fir de
execuie
new Thread(this).start();
} finally {
serverSocket.close();
}
}
public static void main(String[] args)
throws IOException {
SimpleServer server = new SimpleServer();
}
}
67
clientSocket.getInputStream()));
//se trimite o cerere la server
cerere = "duke";
out.println(cerere);
//se asteapta raspuns de la server
raspuns = in.readLine();
System.out.println(raspuns);
} catch (UnknownHostException e) {
System.err.println("Serverul nu poate
fi gasit \n" + e);
System.exit(1);
} finally {
if (out != null)
out.close();
if (in != null)
in.close();
if (clientSocket!= null)
clientSocket.close();
}
}
}
68
69
} finally {
socket.close();
}
70
71
72
} finally {
socket.close();
}
1. Tema lucrrii:
Implementarea aplicaiilor client-server multi-thread
2. Scopul lucrrii:
nsuirea metodelor de utilizare a thread-urilor n Java pentru
aplicaiile client-server
3. Etapele de realizare:
1) Utilizarea clasei Thread pentru crearea unei clase noi;
2) Utilizarea interfeei Runnable pentru crearea i lansarea
de thread-uri;
3) Crearea aplicaiei client / server pentru un singur
utilizator;
4) Crearea aplicaiei client / server pentru un numr fix
de clieni, prin utilizarea thread-urilor;
5) Utilizarea interfeei grafice pentru appleturile multi
user.
4. Exemplu de realizare:
1. Trebuie s includ clasa client
2. Trebuie s includ clasa server
3. Trebuie s includ clasa client / server pentru aplicaia
multiuser bazat pe threaduri
73
// declaration section:
// clientClient: our client socket
// os: output stream
// is: input stream
Socket clientSocket = null;
DataInputStream is = null;
PrintStream os = null;
DataInputStream inputLine =null;
// Initialization section:
// Try to open a socket on port 2222
// Try to open input and output streams
try {
clientSocket = new Socket("localhost", 2222);
os = new
PrintStream(clientSocket.getOutputStream());
is = new
DataInputStream(clientSocket.getInputStream());
inputLine = new DataInputStream(new
BufferedInputStream(System.in));
} catch (UnknownHostException e) {
System.err.println("Don't know about
host");
} catch (IOException e) {
System.err.println("Couldn't get I/O
for the connection to host");
}
74
clean
close
close
close
up:
the output stream
the input stream
the socket
os.close();
is.close();
clientSocket.close();
} catch (UnknownHostException e) {
System.err.println("Trying to
connect to unknown host: " + e);
} catch (IOException e) {
System.err.println("IOException:
+ e);
}
75
"
import java.io.*;
import java.net.*;
public class server {
public static void main(String args[]) {
// declaration section:
// declare a server socket and a client socket for
the server
// declare an input and an output stream
ServerSocket echoServer = null;
String line;
DataInputStream is;
PrintStream os;
Socket clientSocket = null;
//
//
if
//
76
is = new
DataInputStream(clientSocket.getInputStream());
os = new
PrintStream(clientSocket.getOutputStream());
// As long as we receive data, echo that data back
to the client.
while (true) {
line = is.readLine();
os.println("From server: "+ line);
}
}
catch (IOException e) {
System.out.println(e);
}
}
77
wnd_names = new
TextArea("",14,10,TextArea.SCROLLBARS_VERTICAL_ONLY
);
wnd_names.setEditable(false);
to_send = new TextField(50);
b_send = new Button("Send");
Panel for_sends = new Panel();
Panel for_wnds = new Panel();
for_sends.add(to_send);
for_sends.add(b_send);
for_wnds.add(wnd_names);
for_wnds.add(wnd_msg);
add(for_sends,BorderLayout.SOUTH);
add(for_wnds,BorderLayout.CENTER);
setSize(500,340);
setVisible(true);
}
}
class Form extends Dialog implements
ActionListener{
public TextField for_host=null,for_name=null;
public Button begin = null;
public String[] host = null;
public String[] name = null;
Label l_host = new Label("Host:
");
Label l_name = new Label("Name:");
Form(Interface chat,String[] host,String[] name){
super(chat , "Regestration:",true);
setFont(new Font("Comic",Font.BOLD,12));
this.host = host;
this.name = name;
for_host = new TextField(10);
for_name = new TextField(10);
Panel for_texts = new Panel();
for_texts.add(l_host);
for_texts.add(for_host);
for_texts.add(l_name);
for_texts.add(for_name);
begin = new Button("Begin");
begin.addActionListener(this);
Panel for_button = new Panel();
78
for_button.add(begin);
add(for_texts,BorderLayout.CENTER);
add(for_button,BorderLayout.SOUTH);
setBackground(Color.green);
setSize(180,115);
setVisible(true);
}
public void actionPerformed(ActionEvent ae){
host[0] = for_host.getText();
name[0] = for_name.getText();
dispose();
}
}
class Read implements ActionListener{
// Transmiterea mesajului
Interface wnd;
String name="not :";
Socket ss;
PrintWriter out = null;
String fromUser="";
Read(Socket s,Interface w){
wnd=w;
ss=s;
try{
out = new PrintWriter(ss.getOutputStream(),
true);
}catch(IOException io){}
}
public void actionPerformed(ActionEvent ae){
fromUser=wnd.to_send.getText();
wnd.to_send.setText("");
out.println(name+fromUser);
fromUser="";
}
public void setName(String name){
this.name=name+" : ";
}
}
public class ClientMM{
public static void main(String[] args) throws
IOException {
79
80
}
if(fromServer.charAt(0)=='^'){
wnd.wnd_names.append(fromServer.substring(1)+'\n');
}else
wnd.wnd_msg.append(fromServer+"\n");
}
in.close();
kkSocket.close();
}
}
//ServerMM.java
import java.net.*;
import java.io.*;
public class ServerMM {
public static void main(String[] args) throws
IOException {
Socket[] mysocks=new Socket[10];
String[] names = new String[10];
Socket temp_sock = null;
int count=0;
for(int i=0;i<10;i++){
mysocks[i] = null;
names[i] = null;
}
ServerSocket serverSocket = null;
boolean listening = true;
try {
serverSocket = new ServerSocket(8888);
} catch (IOException e) {
System.err.println("Could not listen on
port: 8888.");
System.exit(-1);
}
while (listening){
if(count<10
&&((temp_sock=serverSocket.accept())!=null)){
for(int i=0;i<10;i++){
81
if(mysocks[i]==null){
count=i;
mysocks[i]=temp_sock;
temp_sock=null;
new
ServerThread(mysocks[count],mysocks,count,names).st
art();
break;
}
}
count=0;
for(int i=0;i<10;i++)
if(mysocks[i]!=null) count++;
System.out.println(count);
}else System.out.println("Server is full");
}
}
serverSocket.close();
}
82
new InputStreamReader(
socket.getInputStream()));
String inputLine, outputLine;
while ((inputLine = in.readLine())!= null) {
if (inputLine.equalsIgnoreCase("2112333"))
for(int i = 0;i<10;i++){
if(names[i] != null)
if(name.compareTo(names[i])==0){
names[i] = null;
break;
}
}
for(int i=0;i<10;i++){
if(mys[i]!=null){
outAll = new
PrintWriter(mys[i].getOutputStream(), true);
outAll.println("^#");
for(int j=0;j<10;j++){
if(names[j] != null)
outAll.println(names[j]);
}
outAll = null;
}
}
break;
}
if(inputLine.charAt(0)=='^'){
for(int i = 0;i < 10; i++){
if(names[i] == null){
name = inputLine;
names[i] = inputLine;
break;
}
}
for(int i=0;i<10;i++){
if(mys[i]!=null){
outAll = new
PrintWriter(mys[i].getOutputStream(), true);
83
outAll.println("^#");
for(int j=0;j<10;j++){
if(names[j] != null)
outAll.println(names[j]);
}
outAll = null;
}
}
}else
for(int i=0;i<10;i++){
if(mys[i]!=null){
outAll = new
PrintWriter(mys[i].getOutputStream(), true);
outAll.println(inputLine);
outAll = null;
}
}
}
socket.close();
mys[own_num]=null;
out.close();
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
5. Probleme propuse:
1. Se cere elaborarea unei perechi de programe client-server cu
urmtoarea funcionalitate:
serverul creeaz la prima conectare a unui client un
fiier text vid cu numele acestuia (clientului);
clientul poate trimite serverului unul sau mai multe
fiiere i cere interclasarea acestora cu fiierul care-i
84
85
87
89