PDA

Επιστροφή στο Forum : Java Threads



iasonakos
27-12-08, 15:06
Γεια χαρα σε ολους!
Πρωτα απ' ολα χρονια πολλά!

Εχω μια εργασια πανω σε java και εχω κολλησει σε ενα συγκεκριμενο σημειο!

Ουσιαστιακα η εργασια ειναι για εναν server και 5 clients οι οποιοι συνδεονται στον server χρησιμοποιοντας UDP. Μια υλοποιηση για αυτο το προγραμμα ειναι να σηκωσω εναν server στο μηχανημα μου (sever.java) και 5 διαφορετικους clients (client1.java, client2.java, client3.java, client4.java, client5.java).
Προειμενου να μην καθομαι να γραφω 5 φορες τον ιδιο ακριβως κωδικα, αλλάζοντας μονο την port του client (o server ανοιγει την πορτα 2000 και οι clients χρησιμοποιουν απο πχ. 2001-2005) σκεφτηκα να χρησιμοποιησω Threads.
Εχω φτιαξει ενα main.java αρχειο οπου απο εκει καλώ την ρουτινα launchClient() και μου σηκωνει εναν client.

Αν βάλω

launchClient();
launchClient();
launchClient();
launchClient();
launchClient();

αυτο που κανει το προγραμμα ειναι να σηκωσει τον πρωτο client και μολις τελειωσει προσπαθει να σηκωσει τον δευτερο.
Ομως ο server εχει σταματησει να ακουει (listening)... Ως αποτελεσμα πεταει exception και το προγραμμα τερματιζει.

Φτιαχνοντας 5 διαφορετικους clients (client1.java, client2.java, client3.java, client4.java, client5.java) και τρεχοντας πρωτα τον server και μετα τους clients το προγραμμα παιζει κανονικα μιας και ολοι οι clients τρεχουν ταυτοχρονα!

Πως μπορω να σηκωσω ταυτοχρονα 5 clients χωρις να φτιαξω 5 διαφορετικά αρχεία?
Μεχρι στιγμης μου τους σηκωνει σειριακα... Τον εναν μετα τον αλλον. Και φυσικα το προγραμμα δεν δουλευει!

Οποιαδηποτε βοηθεια θα ειναι τρομερο χριστουγεννιατικο δωρο!!!

Ευχαριστω!
J.

murray
27-12-08, 15:55
Μήπως μπορείς να ποστάρεις τον κώδικα της launchClient() ; Η κλάση Client κάνει extend την κλάση Thread ή implement το interface Runnable; Πολύ φοβάμαι πως όχι και τότε είναι απόλυτα λογικό που το πρόγραμμά σου σηκώνει τους clients σειριακά. Η lauchClient() είναι (μάλλον) μία απλή συνάρτηση, που σημαίνει ότι το πρόγραμμα περιμένει να τερματιστεί ο ένας Client και να επιστρέψει η launchClient() προτού καλέσει την επόμενη launchClient() , και όχι μία συνάρτηση η οποία δημιουργεί ένα thread Client και επιστρέφει αμέσως. Αλλά για να μπορούμε να μιλάμε πιο συγκεκριμένα, please post your source code!

Rama
27-12-08, 16:34
Επίσης δεν χρειάζεται να γράψεις τον ίδιο κώδικα 5 φορές αλλάζοντας μόνο το port. Μπορείς να το περνάς και παραμετρικά και να αποφύγεις τα threads.
Τώρα που το σκέφτομαι ... το server socket σου δεν αλλάζει port. Θα έπρεπε λοιπόν να "χτυπάς" πάντα στο ίδιο port, στο οποίο αυτό ακούσει.
Τέλος ρίξε μία ματιά και εδώ (http://java.sun.com/docs/books/tutorial/essential/concurrency/index.html).

Lucky Luke
27-12-08, 18:15
Στην ουσία αυτό που πρέπει να κάνεις είναι να έχεις μία κλάση server και μία client. Η κλάση server θα δέχεται μηνύματα από τους clients και για κάθε νέα αίτηση από τους clients θα "σηκώνει" ένα thread που θα κάνει τη δουλειά. Αυτό το thread θα αποτελεί μία τρίτη κλάση που θα χρειαστείς.

Επειδή πριν λίγο καιρό είχα να κάνω κάτι παρόμοιο έχω κάποιο κώδικα που μπορεί να σε βοηθήσει. Χρησιμοποιεί TCP sockets αλλά πιστεύω θα βγάλεις άκρη με τη λογική και θα το προσαρμόσεις στα μέτρα σου. Επίσης την port για τον κάθε client μπορείς να τη δίνεις παραμετρικά ώστε να μην αλλάζεις συνέχεια τον κώδικα, όπως έγραψε και ο Rama.

iasonakos
27-12-08, 18:29
Ο δικος μου ο κωδικας μεχρι στιγμης ειναι αυτος:

import java.io.*;
import java.net.*;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Scanner;
import java.lang.Thread;

import server.server;

import client.pack.client;
import client.pack.client_engine;
import client.pack.client_engine2;



public class Main {
private static boolean serverLaunched;
private static boolean clientLaunched;
private static Scanner in = new Scanner(System.in);
private static ArrayList<client_engine> clients = new ArrayList<client_engine>();

static client mam; //name of the client instance mam
static void launchServer()
{
System.out.println(Thread.currentThread().getName() + "Starting Server Thread...");
server.main(null);
setServerLaunched(true);
}

public static void setServerLaunched(boolean serverLaunched) {
Main.serverLaunched = serverLaunched;
}

public static boolean isServerLaunched() {
return serverLaunched;
}

/*static void launchClient() throws IOException
{
System.out.println(Thread.currentThread().getName() + "Starting Client Thread...");
client_engine.main(null);
setClientLaunched(true);

}

public static void setClientLaunched(boolean clientLaunched) {
Main.clientLaunched = clientLaunched;
}

public static boolean isClientLaunched() {
return clientLaunched;
} */
//static String ipAddress = "127.0.0.1";
//static int port = 2010;

static void launchClient1() throws IOException
{
System.out.println(Thread.currentThread().getName() + "Starting Client Thread " + (clients.size()+1) + "..."); clients.add(new client_engine());
client_engine.main(null);
//client_engine2.main(null);
//int port = 2001;

}
static void launchClient2() throws IOException
{
System.out.println(Thread.currentThread().getName() + "Starting Client Thread " );
//client_engine.main(null);
client_engine2.main(null);
//int port = 2001;

}
private static void client(client client) {
// TODO Auto-generated method stub

}

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

launchClient1();
launchClient1();

//client_engine.portNumber=client_engine.portNumber + 3;
//launchClient2();

}
}


αλλα φυσικα δεν δουλευει...

Lucky Luke
27-12-08, 18:41
Το exception που αναφέρεις στο πρώτο post ίσως να οφείλεται στο γεγονός ότι στη main καλείς 2 φορές την launchClient1(). Αν η κλήση client_engine.main(null) δεσμεύει κάποιο port τότε με τη δεύτερη κλήση της launchClient1() πας να δεσμεύσεις το ίδιο port και γι' αυτό πετάγεται το Exception.

Αν δε βγάλεις άκρη, κοίτα και τον κώδικα που έχω παραθέσει στο προηγούμενό μου post.

iasonakos
27-12-08, 19:41
Μοναχικε καουμπου δεν εχεις αδικο!!
Το γνωριζω αυτο! Προφανως και δεν μπορει να παιξει το συγκεκριμενο γιατι δεν του αλλαζω την πορτα.
Το θεμα ειναι πως θα κανω το συγκεκριμενο αρχειο να τρεχει ταυτοχρονα 5 φορες το launchClient()??

Η λειτουργια του προγραμματος ειναι ως εξης:
Τρεχω τον server (ο οποιος καθεται και ακουει) και επειτα τρεχω τους clients. 5 διαφορετικα αρχεια (διαφορετικη πορτα ο καθε client).
Παω μετα στον server, παταω enter στην κονσολα και κανει την δουλεια που πρεπει.

Αυτο που θελω να κανω ειναι να τρεξω ταυτοχρονα 5 clients με διαφορετικα ports πατωντας ομως μονο την main.java να τρεξει και οχι 5 διαφορετικα αρχεια..

Lucky Luke
27-12-08, 19:58
Επειδή δεν έχω όλο τον κώδικα (αυτά τα imports που έχεις κάνει) δεν μπορώ να σου πω ακριβώς τι να κάνεις.

Δεν καταλαβαίνω πάντως για ποιο λόγο να πρέπει να τα τρέχεις όλα μέσα από ένα αρχείο java. Έχεις οδηγίες ότι πρέπει σώνει και καλά να τα βάλεις όλα σε ένα αρχείο; Θεωρώ ότι είναι πιο σωστό να σπάσεις τον κώδικά σου όπως είναι στο συνημμένο. Δε θα φτιάξεις 5 διαφορετικά αρχεία client, απλά θα τρέξεις τον ίδιο ακριβώς client 5 φορές με διαφορετικό όρισμα - port κάθε φορά.

Εξάλλου υποτίθεται ότι αυτό το πράγμα που θα φτιάξεις θα πρέπει να παίζει σε πολλά μηχανήματα που θα επικοινωνούν μεταξύ τους (αν κάνω λάθος διόρθωσέ με). Δηλαδή θα έχεις ένα μηχάνημα αφιερωμένο για server και κάποια άλλα clients. Το ότι τα τρέχεις όλα τοπικά προφανώς οφείλεται στο γεγονός έλλειψης πολλών pc. Αλλά και μόνο από την ύπαρξη των sockets αυτό καταλαβαίνω, ότι η προοπτική είναι να παίζει δικτυακά. Αν τα έχεις επομένως όλα μαζί θα γίνει λίγο μπάχαλο.

Τώρα βέβαια αν δε θες να πατήσεις 5 φορές το run για να ξεκινήσεις τους clients φτιάξε μια main η οποία θα φτιάχνει 5 αντικείμενα client (που πιθανόν να κάνουν extend τη Threads για να μην εμποδίζει ο ένας τον άλλο) και ο κώδικας που έχει στην main του o Client που σου έχω δώσει να γίνει copy paste στη μέθοδο run() του δικού σου client-thread.

Αυτό μου έρχεται αυτή τη στιγμή ως πιο κοντικό σε αυτό θες να κάνεις.

iasonakos
27-12-08, 20:58
Η εργασια εχει 3 tasks.
1 server 1 client στο ιδιο μηχανημα
1 server 5 clients στο ιδιο μηχανημα
1 server και 5 μηχανηματα οπου το καθενα θα εχει φορτομενο απο 1 client.

To task1 δουλευει.
Το task 3 δουλευει.
Στο task 2 κολλαω.

Θα κοιταξω τον κωδικα σου και θα επανελθω!!

Ευχαριστω πολυ!!!!!!!

dvm
29-12-08, 06:55
Χωρίς να έχω δει την εκφώνηση εγώ νομίζω ότι σου λέει να τρέχεις διαφορετικά προγράμματα.
Δηλαδή:


java test.Server 5000
java test.Client 6001
java test.Client 6002
java test.Client 6003
java test.Client 6004
java test.Client 6005


Όπως είπαν και τα παιδιά ο κώδικας του client δεν χρειάζεται να ξαναγραφτεί, απλά τον τρέχεις 5 φορές.
Τώρα αν σου έχει ζητήσει ο καθηγητής threads πάω πάσο. Θα σου πρότεινα τότε να διαβάσεις το Tutorial της
sun για τα threads (http://java.sun.com/docs/books/tutorial/essential/concurrency/).

nikospara
29-12-08, 12:06
Γειά iasonakos,

Δές τον κώδικα του Lucky Luke, είναι ο σωστός για τέτοιες περιπτώσεις, εκτός αν έχεις κάτι πολύ ειδικό. Η λογική στην απλούστερη μορφή της είναι:

- Ξεκινάει ένας server, δηλ διαδικασία που ακούει (socket listen) σε συγκεκριμένη πόρτα.
- Η εκτέλεση του κώδικα που δέχεται σύνδεση από client (socket accept) γίνεται σε loop.
- Με κάθε σύνδεση, ο server σηκώνει ένα ξεχωριστό thread που εξυπηρετεί τη σύνδεση για όσο χρειαστεί. Το main thread του server επιστρέφει γρήγορα στο listen-accept loop.
- Όταν ο client τελειώσει, το thread που τον εξυπηρετούσε τερματίζει.

Η λογική αυτή (σε πιο προχωρημένες παραλλαγές - πχ thread pooling) εφαρμόζεται σε όλους τους servers.

iasonakos
31-12-08, 15:16
Γεια χαρα και παλι σε ολους!

Ισως τελικα να μην χρειαζομαι να το φτιαξω με Threads.
Το μονο που θελω ειναι με ενα run να μπορω να τρεχω 5 φορες τον ιδιο κωδικα με διαφορετικη πορτα ως ορισμα!
Ουτε αυτο δεν ξερω πως να το φτιαξω...
Πατωντας δηλαδη το run του eclipse μια φορα να τρεχει μου τρεχει 5 φορες (αλλα ταυτοχρονα για να μην σταματησει ο server) τον client.
Η λογικη του προγραμματος:
Τρεχω τον server o οποιος ακουει.
Τρεχω 5 clients (προς το παρον 5 διαφορετικα αρχεια με τον ιδιο κωδικα και διαφορετικη πορτα)
Οταν σηκωθουν και οι 5 clients παω στην κονσολα του server, παταω enter και ξεκιναει την δουλεια του ο server.
Αν τρεξει ενας client και τελειωσει την δουλεια τους τοτε ο server κλεινει και ο δευτερος που παει να σηκωθει σειριακα πεταει exception μιας και δεν βρηκε ανοιχτο server για να συνδεθει.

Προσπαθησα να το κανω με threads, ακολουθησα τις οδηγιες σας αλλα τρεχοντας την main class μου η οποια περιεχει τα threads αυτο που κανει ειναι να μου ανοιγοκλεισει τον client!!
Δηλαδη μεσα σε λιγοτερο απο 1 δευτερολεπτο, ανοιγει και μετα γινεται terminate.

mpetou
01-01-09, 19:51
fail!
threads sto server no threads sto client

καλη χρονια!

Lucky Luke
02-01-09, 14:41
Αν τρεξει ενας client και τελειωσει την δουλεια τους τοτε ο server κλεινει και ο δευτερος που παει να σηκωθει σειριακα πεταει exception μιας και δεν βρηκε ανοιχτο server για να συνδεθει.
Σιγουρέψου ότι έχεις βάλει τον κώδικα του server μέσα σε ένα while (true) {} loop διαφορετικά λογικό είναι να "σκάει" το πρόγραμμα, αφού μετά την εξυπηρέτηση του πρώτου client ο server λογικά κλείνει.

absolut
08-06-10, 18:09
θα ήμουν υπόχρεος αν θα μπορούσε κάποιος να με βοηθήσει με την παρακάτω άσκηση...


Γράψτε πρόγραμμα που να ξεκινάει (“πυροδοτεί”) 1000 νήματα (threads).
Κάθε νήμα προσθέτει 1 σε μια μεταβλητή sum που είναι αρχικά 0.
Τρέξτε το πρόγραμμα με συγχρονισμό και χωρίς, παρατηρείστε αν υπάρχει διαφορά.
Ορίστε την sum σαν Integer wrapper object,
{π.χ private Integer sum = new Integer(0) }
Έτσι ώστε να περνάει με αναφορά (by reference) σε κάθε thread.
(~ 15 γραμμές εκτελέσιμου κώδικα, Java6)

Όποιος μπορεί παρακαλώ να με βοηθήσει.

@ ADSLgr.com All rights reserved.