简体   繁体   中英

How can I make this code wait until a Thread is available in the Thread Pool?

I wanted to practice a little on Network Programming and Thread Pools with Java. Here is a sample code I written:

/* User: koray@tugay.biz Date: 21/02/15 Time: 13:30 */

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class MyServer {

    static List<ServerSocketThread> myThreadPool = new ArrayList<ServerSocketThread>();
    static int numberOfCurrentConnections = 0;

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

        ServerSocket serverSocket = new ServerSocket(8888);

        ServerSocketThread threadOne = new ServerSocketThread(null);
        ServerSocketThread threadTwo = new ServerSocketThread(null);

        myThreadPool.add(threadOne);
        myThreadPool.add(threadTwo);

        while (true) {
            if(numberOfCurrentConnections < 2) {
                Socket accept = serverSocket.accept();
                ServerSocketThread thread = myThreadPool.get(numberOfCurrentConnections);
                thread.setSocket(accept);
                thread.start();
                numberOfCurrentConnections++;
            } else {
                // I want to force the client to wait until a new Thread is available from the pool.
            }
        }

    }

    public static void informFinished() {
        numberOfCurrentConnections--;
    }

}

and the ServerSocketThread class is as follows:

/* User: koray@tugay.biz Date: 21/02/15 Time: 18:14 */

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

public class ServerSocketThread extends Thread {

    Socket socket;

    public ServerSocketThread(Socket accept) {
        this.socket = accept;
    }

    @Override
    public void run() {

        try {

            Scanner scanner = new Scanner(socket.getInputStream());
            String readLine;

            while (!(readLine = scanner.nextLine()).equals("bye")) {
                System.out.println(readLine);
            }

            new PrintWriter(socket.getOutputStream()).write("Bye then..");
            socket.close();
            MyServer.informFinished();

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public void setSocket(Socket socket) {
        this.socket = socket;
    }

}

Well I can connect to my server with 2 different terminals like this just fine:

Korays-MacBook-Pro:~ koraytugay$ telnet localhost 8888
Trying ::1...
Connected to localhost.
Escape character is '^]'.
laylay
bombom

And the 3rd connection (if made) will not be served as there are 2 Threads only in the Thread Pool. But I can not find a way to make the 3rd client wait until a client says "bye". What I want to do is, after one of the 2 first connected clients disconnect, a Thread is allocated to the waiting 3rd Client, but how?

I will answer my own question, I made it work like this:

/* User: koray@tugay.biz Date: 21/02/15 Time: 21:12 */

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Stack;

public class MyConnectionAccepter {

    private Stack<MySocketThread> mySocketThreads = new Stack<MySocketThread>();
    private volatile int currentNumberOfConnections = 0;

    public MyConnectionAccepter() {

        MySocketThread mySocketThreadOne = new MySocketThread(this);
        MySocketThread mySocketThreadTwo = new MySocketThread(this);

        mySocketThreadOne.setDaemon(true);
        mySocketThreadTwo.setDaemon(true);

        mySocketThreadOne.start();
        mySocketThreadTwo.start();

        mySocketThreads.push(mySocketThreadOne);
        mySocketThreads.push(mySocketThreadTwo);

    }

    public void start() throws IOException {

        ServerSocket serverSocket = new ServerSocket(8888);

        while (true) {
            while (currentNumberOfConnections < 2) {
                System.out.println("Blocking now:");
                Socket accept = serverSocket.accept();
                System.out.println("Connection accepted..");
                MySocketThread mySocketThread = mySocketThreads.pop();
                mySocketThread.setSocket(accept);
                System.out.println("Incrementing connections..");
                currentNumberOfConnections++;
                System.out.println("End of while..");
            }
        }

    }

    public void informIAmDone(MySocketThread mySocketThread) {
        mySocketThreads.push(mySocketThread);
        currentNumberOfConnections--;
    }
}

and

/* User: koray@tugay.biz Date: 21/02/15 Time: 21:04 */

import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;

public class MySocketThread extends Thread {

    private volatile Socket socket;
    MyConnectionAccepter myConnectionAccepter;

    public MySocketThread(MyConnectionAccepter myConnectionAccepter) {
        this.myConnectionAccepter = myConnectionAccepter;
    }

    @Override
    public synchronized void run() {
        System.out.println("Started...");
        serve();
    }

    public void setSocket(Socket socket) {
        this.socket = socket;
        System.out.println("Socket not null anymore..");
    }

    public void serve() {
        while(socket == null) {

        }
        while (socket != null) {
            Scanner scanner = null;
            try {
                scanner = new Scanner(socket.getInputStream());
            } catch (IOException e) {
                e.printStackTrace();
            }
            String readLine;
            while (!(readLine = scanner.nextLine()).equals("bye")) {
                System.out.println(readLine);
            }
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            socket = null;
            myConnectionAccepter.informIAmDone(this);
        }
        serve();
    }

}

and the Test Class:

/* User: koray@tugay.biz Date: 21/02/15 Time: 21:18 */

import java.io.IOException;

public class MyTestClass {

    public static void main(String[] args) throws IOException {
        MyConnectionAccepter myConnectionAccepter = new MyConnectionAccepter();
        myConnectionAccepter.start();
    }
}

I would suggest that you should create a threadpool as described in this article: http://tutorials.jenkov.com/java-concurrency/thread-pools.html

So basically in addition to the pool of threads you also maintain a queue of tasks. Each thread in the pool is continuously polling the task queue for tasks. Whenever a task is available (queue is not empty), it is picked up by a thread and executed. In your case the task would be handling the client connection. The the number of threads in the pool is limited ( 2 in this case). So at any time number of connections that can be processed simultaneously is 2. Only when one of two threads is done executing the current task will it pick the next one. Each time you receive a new connection request, you add a new task to the queue.

Hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM