如何让此代码等待线程池中的线程可用?
How can I make this code wait until a Thread is available in the Thread Pool?
我想用 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 class如下:
/* 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
并且第三个连接(如果建立)将不会被服务,因为线程池中只有 2 个线程。但是我找不到让第三个客户等到客户说 "bye" 的方法。我想做的是,在 2 个第一个连接的客户端之一断开连接后,一个线程被分配给等待的第三个客户端,但是如何?
我会回答我自己的问题,我是这样工作的:
/* 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();
}
}
和测试 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();
}
}
我建议您按照本文所述创建一个线程池:http://tutorials.jenkov.com/java-concurrency/thread-pools.html
所以基本上除了线程池之外,您还需要维护一个任务队列。池中的每个线程都在不断地轮询任务队列中的任务。只要有任务可用(队列不为空),它就会被线程拾取并执行。在您的情况下,任务是处理客户端连接。池中的线程数是有限的(在本例中为 2)。所以在任何时候,可以同时处理的连接数是 2。只有当两个线程之一完成当前任务时,它才会选择下一个。每次收到新的连接请求时,都会向队列中添加一个新任务。
希望对您有所帮助!
我想用 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 class如下:
/* 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
并且第三个连接(如果建立)将不会被服务,因为线程池中只有 2 个线程。但是我找不到让第三个客户等到客户说 "bye" 的方法。我想做的是,在 2 个第一个连接的客户端之一断开连接后,一个线程被分配给等待的第三个客户端,但是如何?
我会回答我自己的问题,我是这样工作的:
/* 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();
}
}
和测试 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();
}
}
我建议您按照本文所述创建一个线程池:http://tutorials.jenkov.com/java-concurrency/thread-pools.html
所以基本上除了线程池之外,您还需要维护一个任务队列。池中的每个线程都在不断地轮询任务队列中的任务。只要有任务可用(队列不为空),它就会被线程拾取并执行。在您的情况下,任务是处理客户端连接。池中的线程数是有限的(在本例中为 2)。所以在任何时候,可以同时处理的连接数是 2。只有当两个线程之一完成当前任务时,它才会选择下一个。每次收到新的连接请求时,都会向队列中添加一个新任务。
希望对您有所帮助!