Pont à sens unique avec des voitures générés par un host éloigné


Le pont - ressource (moniteur). Les voitures le prennent s'il est libre ou bien si sur le pont il y a des voitures circulent en même direction. Sans exigence d'alterner les voitures de droite et de gauche.

public class Bridge {
    private int nVh, countSeq, maxCount;
    private boolean open;
    Bridge(int maxCount){
        nVh = countSeq=0;
        open = true;
        this.maxCount=maxCount;
    }
    synchronized public int brN(){
        return nVh;
    }
    synchronized public void takeB(boolean lr ){
        while((nVh>0)&& (lr==true)||
              (nVh<0) && (lr==false)|| !open){
            System.out.println("\t"+Thread.currentThread().getName()+" waiting");
            try{     wait();   }
            catch(InterruptedException e){
                System.err.println(e);
            }
        }
        countSeq++;
        if (lr) nVh--;
        else nVh++;
        System.out.println(Thread.currentThread().getName()+" on the bridge in the same direction: "+countSeq);
        if (countSeq==maxCount){open = false; System.out.println("The bridge is closed");}
    }
    synchronized public void leaveB(boolean lr ){
        if (nVh>0) nVh--;
        else nVh++;
        System.out.println("\t\t"+Thread.currentThread().getName()+" leave the bridge");
        if(nVh==0){countSeq=0;open = true; System.out.println("The bridge is open");}
        notifyAll();
    }
}

Voiture locale (Thread). Le pont et la direction - paramètres du constructeur.

public class Vehicle extends Thread{
    private boolean lr;
    private Bridge b;
    private String name;
    private static int num;
    Vehicle(boolean lr, Bridge b){
        this.lr=lr;
        this.b = b;
        name = "V "+ ++num + (lr?" left->":" <-right");
        super.setName(name);
    }
    public void run(){
        try {
            sleep((int)(Math.random()*600));
        } catch (InterruptedException e){}
        b.takeB(lr);
        try {
            sleep(2000);
        } catch (InterruptedException e){}
        b.leaveB(lr);
    }
}

Serveur. Ecoute sur le port 8080. S’il y a demande il lance un thread pour servir  un client éloigné - ServeOneVehicle.

import java.io.*;
import java.net.*;
public class Server extends Thread{
    private static final int PORT = 8080;
    private ServerSocket s=null;
    private Bridge b;
    Server(Bridge b){
        this.b=b;
    }
    public void run(){
        try {
            s = new ServerSocket(PORT);
            System.out.println("Server Started");
            while(true) {
                // Blocks until a connection occurs:
                Socket socket = s.accept();
                try {
                    new ServeOneVehicle(socket,b);
                } catch(IOException e) {
                    // If it fails, close the socket,
                    // otherwise the thread will close it:
                    socket.close();
                }
            }
        }
        catch(Exception ioe){}
        try {
            s.close();
        }
        catch(Exception ioe){}       
    }
}

Thread pour servir  un client éloigné. Attend une demande du client éloigné pour générer une voiture éloigné.

Protocole – deux lignes. La première contient le nom du client, la deuxième – direction de circulation (left ou right).

import java.io.*;
import java.net.*;
class ServeOneVehicle extends Thread {
    private Socket socket;
    private BufferedReader in;
    private PrintWriter out;
    private Bridge b;
    private String name="";
    public ServeOneVehicle(Socket s, Bridge b)  throws IOException {
        socket = s;
        in = new BufferedReader(
                new InputStreamReader(
                  socket.getInputStream()));
        out =   new PrintWriter(
                new BufferedWriter(  new OutputStreamWriter(
                        socket.getOutputStream())),true);
        this.b=b;
        System.out.println("\t\t\tnew remote connection");
        start();    // Calls run()
  }
  public void run() {
      String leftToRight;
      boolean lr;
    try {
        name = in.readLine();
        while (true) {
             leftToRight = in.readLine();
             if (leftToRight.equals("END")) break;
             if(leftToRight.equalsIgnoreCase("Left"))lr=true;
             else lr=false;
             (new RemVehicle(name,lr, b,out)).start();        
        }
        System.out.println("closing connection to "+name);
    } catch (IOException e) {  }
   finally {
      try {
        socket.close();
      } catch(IOException e) {}
    }
  }

La voiture éloignée

Outre le nom, la direction et le pont, comme un paramètre du constructeur est PrintWriter, pour être en mesure d'informer le client élogné pour la circulation  de la voiture. Protocole de communication - deux lignes. La première est envoyée lorsque la voiture prend le pont et la seconde quand la voitrure quitte le pont. L'information affichée au niveau local est déplacée a droite pour être distinguée facilement.

import java.io.PrintWriter;
public class RemVehicle extends Thread{
    private boolean lr;
    private Bridge b;
    private String name="";
    private static int num;
    private PrintWriter out;
    RemVehicle(String name,boolean lr, Bridge b, PrintWriter out){
        this.lr=lr;
        this.b = b;
        this.out=out;
        name += "\t\t\t"+name+ ++num + (lr?" left->":" <-right");
        super.setName(name);
    }
    public void run(){
        try {
            sleep((int)(Math.random()*600));
        } catch (InterruptedException e){}
        b.takeB(lr);
        out.println(name+" take the bridge");
        try {
            sleep(2000);
        } catch (InterruptedException e){}
        b.leaveB(lr);
        out.println(name+" leave the bridge");
    }
}

L'application principale. 

Démarre le serveur d'attente des   clients éligné et  génére de manière cyclique un certain nombre de voitures locales sur demande en serie par 10. 

import java.util.*;
public class Circ {
    public static void main(String arg[]){
        Scanner sc = new Scanner(System.in);
        Bridge b = new Bridge(9);
        (new Server(b)).start();
        try{
            Thread.sleep(50);
        }catch (InterruptedException e){}
        do{
            System.out.println("to start threads localy type Y");
        } while (!sc.nextLine().equalsIgnoreCase("Y"));
        for(int i = 0; i < 50; i++){
            (new Vehicle(true, b)).start();
            try{
                Thread.sleep(100);
            }catch (InterruptedException e){}
            (new Vehicle(false,b)).start();
            if((i%10)==0)
                try{
                    Thread.sleep(1000);
                }catch (InterruptedException e){}
        }
    }
}

Le client éloigné.

Demande le nom du client et 10 fois consecutives la direction d'une nouvelle voiture élognée. Finit après une ligne vide.  Protocole de communication - deux lignes, la première est le nom du client et le numéro de série de la voiture et la deuxième est la direction. Attend  les message de la voiture pour l'entrée et la sortie du pont et les affiche sur la console.

import java.net.*;
import java.io.*;
public class RemVehicleClient {
    private static final int PORT = 8080;
    private static String name;
    public static void main(String[] args)throws IOException {
        String server = null;
        InetAddress addr =  InetAddress.getByName(server);
        System.out.println("addr = " + addr);
        Socket socket = new Socket(addr, PORT);                     
                    //Socket s=new Socket(); //s.connect(new  InetSocketAddress(host,port),timeout);
        // Guard everything in a try-finally to make         
        // sure that the socket is closed:
        try {
            System.out.println("socket = " + socket);
            BufferedReader in =
                    new BufferedReader(
                            new InputStreamReader(socket.getInputStream()));
            BufferedReader sin =  new BufferedReader(
                    new InputStreamReader(System.in));

            // Output is automatically flushed
            // by PrintWriter:
            PrintWriter out =   new PrintWriter(
                    new BufferedWriter(  new OutputStreamWriter(
                            socket.getOutputStream())),true);
            System.out.print("Your name please:");
            name = sin.readLine();
            for(int i = 0; i <10 ; i ++) {
                System.out.print("input Left(left->right) or Right [empty for finish] " + i + ":");
                String s = sin.readLine();
                if(s.length()==0) break;
                if(!(s.equalsIgnoreCase("Left"))&&!(s.equalsIgnoreCase("Right"))) {
                    System.out.println("Left or Right please");
                    continue;
                }
                out.println(name);
                out.println(s);
                System.out.println(in.readLine());    // wait to take the bridge
                System.out.println(in.readLine());    // wait to leave the bridge
            }
            out.println("END");
        }
        finally {
            System.out.println("closing...");
            socket.close();
        }
    }
}