簡體   English   中英

如何使此代碼等待線程池中的線程可用?

[英]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類如下:

/* 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個線程。 但是我找不到讓第三位客戶等到客戶說“再見”的方法。 我想做的是,在兩個第一個連接的客戶端之一斷開連接之后,將一個線程分配給正在等待的第三個客戶端,但是如何?

我將回答我自己的問題,使它像這樣工作:

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

我建議您按照本文所述創建線程池: http : //tutorials.jenkov.com/java-concurrency/thread-pools.html

因此,基本上,除了線程池之外,您還維護一個任務隊列。 池中的每個線程都在不斷輪詢任務隊列中的任務。 只要有任務可用(隊列不為空),線程就會將其拾取並執行。 在您的情況下,任務將是處理客戶端連接。 池中的線程數是有限的(在這種情況下為2)。 因此,任何時候可以同時處理的連接數是2。只有當兩個線程之一完成執行當前任務時,它才會選擇下一個。 每次收到新的連接請求時,便將新任務添加到隊列中。

希望這可以幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM