如何在线程池中的线程可用之前等待此代码?

时间:2015-02-21 18:49:40

标签: java multithreading sockets networking

我想在网络编程和线程池上练习一点Java。这是我编写的示例代码:

/* 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--;
    }

}

和ServerSocketThread类如下:

/* 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;
    }

}

好吧,我可以使用2个不同的终端连接到我的服务器,就好了:

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

第3个连接(如果已建立)将不会被提供,因为线程池中只有2个线程。但我找不到让第三个客户等到客户说“再见”的方法。我想要做的是,在2个第一个连接的客户端中的一个断开后,一个线程被分配给等待的第三个客户端,但是如何?

2 个答案:

答案 0 :(得分:0)

我会回答我自己的问题,我让它像这样工作:

/* 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--;
    }
}

/* 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();
    }

}

和测试类:

/* 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();
    }
}

答案 1 :(得分:0)

我建议你应该按照本文所述创建一个线程池:http://tutorials.jenkov.com/java-concurrency/thread-pools.html

所以基本上除了线程池之外,你还要维护一个任务队列。池中的每个线程都在不断轮询任务队列以查找任务。只要任务可用(队列不为空),它就会被线程拾取并执行。在您的情况下,任务将是处理客户端连接。池中的线程数是有限的(在这种情况下为2)。因此,在任何时候可以同时处理的连接数是2.只有当两个线程中的一个完成执行当前任务时,它才会选择下一个。每次收到新的连接请求时,都会向队列中添加一个新任务。

希望这有帮助!