One-way bridge with cars generated by a remote host


The bridge - resource (monitor). Cars take it if it is free or if on the bridge there are cars traveling in the same direction. Requirement to alternate cars on the right and left.

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 ){
        boolean waiting=false;   //to print waiting only once for vehicle
        while((nVh>0)&& (lr==true)||
                (nVh<0) && (lr==false)|| !open){
            if(!waiting) {
                System.out.println("\t"+Thread.currentThread().getName()+" waiting");
                waiting=true;
            }
            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();
    }
}

Local or remote car (Thread). The name (null for locale), direction, bridge, and PrintWriter (null for locale) - constructor parameters.

//for local in constructor's parameter:  name=out=null
import java.io.PrintWriter;

public class Vehicle extends Thread{
  private boolean lr;
  private Bridge b;
  private String name;
  private static int num;
  private PrintWriter out;
  Vehicle(String name,boolean lr, Bridge b, PrintWriter out){
      this.lr=lr;
      this.b = b;
      this.out=out;
      if(name==null)this.name = "V "+ ++num + (lr?" left->":" <-right");  //local vehicle
      else this.name = "\t\t\t"+name + " remote"; //remote vehicle
      super.setName(this.name);
  }
  public void run(){
      try {
          sleep(3000);
      } catch (InterruptedException e){}
      if (out!=null){         //remote
          out.println(name+ " wait to take the bridge");
      }
      b.takeB(lr);
      if (out!=null){         //remote
          out.println(name+ " is on the bridge");
      }
      try {
          sleep(6000);
      } catch (InterruptedException e){}
      b.leaveB(lr);
      if(out!=null)out.println(name+" leave the bridge");          //remote
  }
}

Server. Listens on port 8082. If there is a request it launches a thread to serve a remote client - ServeOneVehicle..

import java.io.*;
import java.net.*;
public class Server extends Thread{
    private static final int PORT = 8082;
    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 to serve a remote client. Waits for a request from the remote client to generate a remote car.

Protocol – two lines. The first contains the name of the vehicle, the second – direction of traffic (left or right). The following lines - new traffic directions, the empty line - end of session


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 Vehicle(name,lr, b,out)).start();       
        }
        System.out.println("closing connection to "+name);
    } catch (IOException e) {  }
   finally {
      try {
        socket.close();
      } catch(IOException e) {}
    }
  }
}
 


The main application.

 Start the remote client waiting server and cyclically generate local vehicles in series by 10.
public class Circ {
    public static void main(String arg[]){
       
        Bridge b = new Bridge(3);
        (new Server(b)).start();
        for(int i = 1; ; i++){
            (new Vehicle(null,Math.random()>0.5?true:false, b,null)).start();
            try{
                Thread.sleep(1000);
            }catch (InterruptedException e){}
            if((i%10)==0)
                try{
                    Thread.sleep(10000);
                }catch (InterruptedException e){}
        }
    }
}

The remote vehicle.

Requests the name and consecutive directions of passage of a new remote vehicle. Waits for messages from the vehicle for entering and exiting the bridge and displays them on the console. End after an empty line.

import java.net.*;
import java.io.*;
public class RemVehicleClient {
    private static final int PORT = 8082;
    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();
            out.println(name);
            for(;;) {
                System.out.print("input L(left->right) or R(right->left) [empty for finish] :");
                String s = sin.readLine();
                if(s.length()==0) break;
                if(!(s.equalsIgnoreCase("L"))&&!(s.equalsIgnoreCase("R"))) {
                    System.out.println("L or R or 'Enter' please");
                    continue;
                }

                out.println(s.equalsIgnoreCase("L")?"Left":"Right");
                System.out.println(in.readLine());    // wait to take the bridge
                System.out.println(in.readLine());    // take the bridge
                System.out.println(in.readLine());    // leave the bridge
            }
            out.println("END");
        }
        finally {
            System.out.println("closing...");
            socket.close();
        }
    }
}