ExecutorService会消耗线程容量。

huangapple go评论74阅读模式
英文:

Does ExecutorService consume thread capacity

问题

我正在尝试创建一个消息应用程序。我有一个名为 MessageServer 的类,我打算将客户端连接到这个类上。
每个 Client 类都实现了 Runnable 接口。
我的方法是在 MessageServer 类内部创建一个 ExecutorService,然后从这里执行每个客户端。

我的问题是,我可以根据 Executors.newFixedThreadPool(x) 执行无限数量的 Runnable 吗,还是它们会被视为独立的线程?

如果可能的话,我也愿意采用新的方法。
我还从主方法中启动了 MessageServer 线程。

MessageServer

public class MessageServer extends Server implements Runnable{
    
    static LinkedList<Message> messages = new LinkedList<>();
    
    LinkedList<Client> clients = new LinkedList<>();

    ExecutorService clientPool = Executors.newFixedThreadPool(3);

    public MessageServer() throws IOException {
        super(Vars.MESSAGE_PORT);
    }

    public void addToMessages(Message message) {
        if (!messages.contains(message)) {
            messages.add(message);
        }
    }

    @Override
    public void run() {
        while(true){
            try {
                Socket client = serverSocket.accept();
                
                // 读取客户端数据然后添加到列表
                ObjectOutputStream out = new ObjectOutputStream(client.getOutputStream());
                ObjectInputStream in =  new ObjectInputStream(client.getInputStream());
                
                Client current = (Client)in.readObject();
                clients.add(current);
            } catch (Exception ex) {
                Logger.getLogger(MessageServer.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}

超类 Server

public class Server{
    InetAddress address;
    
    LinkedList<Client> clients = new LinkedList<>();
    
    protected ServerSocket serverSocket;

    public Server(int port) throws IOException {
        serverSocket = new ServerSocket(port);
        serverSocket.setSoTimeout(Vars.SERVER_TIMEOUT_MS);
        
        // ip = Utilities.getIp();
        
        address = serverSocket.getInetAddress();
    }
}

Client

public class Client implements Serializable {

protected String nickname;
protected long id;
protected int key;

// MessageServer
protected transient ObjectOutputStream msgOut;
protected transient ObjectInputStream msgIn;
protected transient Socket messageSocket;

protected transient Socket videoSocket;


public Client(String nickname){
    this.nickname = nickname;
    createid();
    makeConnection();
    key = (int) (Math.random() * 8999) + 1000;
}

void makeConnection(){
    try {
        messageSocket = new Socket(Vars.IP, Vars.MESSAGE_PORT);
        //TODO 与 videoServer 建立连接
        msgOut = new ObjectOutputStream(messageSocket.getOutputStream());
        msgIn = new ObjectInputStream(messageSocket.getInputStream());
        
        msgOut.writeObject(this);
        
    } catch (IOException ex) {
        Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
    }
}

final void createid(){
    id = 3;
    id = 13 * id + Objects.hashCode(this.nickname);
}

// 获取器-设置器-哈希码-相等
}

希望这能帮助你!

英文:

I am trying to create a messaging application. I have a class called MessageServer and I intend to connect clients to this class.
Every Client class implements Runnable.
My approach is to create an ExecutorService inside the MessageServer class, and execute every client from here.

My question is, can I execute infinite amount Runnable's depending on the Executors.newFixedThreadPool(x) or do they count as individual threads?

I am open to new approaches if possible.
I also start the MessageServer thread from main method.

MessageServer

public class MessageServer extends Server implements Runnable{
    
    static LinkedList&lt;Message&gt; messages = new LinkedList&lt;&gt;();
    
    LinkedList&lt;Client&gt; clients = new LinkedList&lt;&gt;();

    ExecutorService clientPool = Executors.newFixedThreadPool(3);

    public MessageServer() throws IOException {
        super(Vars.MESSAGE_PORT);
    }

    public void addToMessages(Message message) {
        if (!messages.contains(message)) {
            messages.add(message);
        }
    }

    @Override
    public void run() {
        while(true){
            try {
                Socket client = serverSocket.accept();
                
                //Read Client data then add to the list
                ObjectOutputStream out = new ObjectOutputStream(client.getOutputStream());
                ObjectInputStream in =  new ObjectInputStream(client.getInputStream());
                
                Client current = (Client)in.readObject();
                clients.add(current);
            } catch (Exception ex) {
                Logger.getLogger(MessageServer.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        
    }

}

Super class Server

public class Server{
    InetAddress address;
    
    LinkedList&lt;Client&gt; clients = new LinkedList&lt;&gt;();
    
    protected ServerSocket serverSocket;

    public Server(int port) throws IOException {
        serverSocket = new ServerSocket(port);
        serverSocket.setSoTimeout(Vars.SERVER_TIMEOUT_MS);
        
        //ip = Utilities.getIp();
        
        address = serverSocket.getInetAddress();
    }
}

Client

public class Client implements Serializable {

protected String nickname;
protected long id;
protected int key;

// MessageServer
protected transient ObjectOutputStream msgOut;
protected transient ObjectInputStream msgIn;
protected transient Socket messageSocket;

protected transient Socket videoSocket;


public Client(String nickname){
    this.nickname = nickname;
    createid();
    makeConnection();
    key = (int) (Math.random() * 8999) + 1000;
}

void makeConnection(){
    try {
        messageSocket = new Socket(Vars.IP, Vars.MESSAGE_PORT);
        //TODO make connection with videoServer
        msgOut = new ObjectOutputStream(messageSocket.getOutputStream());
        msgIn = new ObjectInputStream(messageSocket.getInputStream());
        
        msgOut.writeObject(this);
        
    } catch (IOException ex) {
        Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
    }
}

final void createid(){
    id = 3;
    id = 13 * id + Objects.hashCode(this.nickname);
}

// Getters-setters-hashcode-equals

答案1

得分: 2

> 我的问题是,我是否可以根据Executors.newFixedThreadPool(x)执行无限数量的Runnable,还是它们被视为单独的线程?

您可以添加比线程更多的可运行项。它们存储在队列中,并在有可用线程时执行。

Executors.newFixedThreadPool方法的Javadoc中:

> 创建一个线程池,它重用固定数量的线程,这些线程在共享的无限队列中运行。

所以,是的,它是“无限的”。

英文:

> My question is, can I execute infinite amount Runnable's depending on the Executors.newFixedThreadPool(x) or do they count as individual threads?

You can add far more runnables than threads. They are stored in a queue, and executed when a thread is available.

In the Javadoc of the Executors.newFixedThreadPool method:

> Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue.

So, yes, it's "infinite".

答案2

得分: 2

> 我的问题是,我是否可以根据Executors.newFixedThreadPool(x)执行无限数量的Runnable,还是它们算作单独的线程?

具有固定大小的线程池在内部有一个队列,任务会被排队在那里。每个Runnable都会被放入该队列中。如果一个线程完成了当前的任务,它会从队列中获取新的任务。

您可以排队的任务数量没有限制,除非受到硬件限制。例如,当您排队了20个任务,并且池中有10个线程时,只有其中的10个任务,或者更确切地说,只有10个Runnable会被执行。在您的情况下,只有x个客户端会在运行,因为池中只有x个固定大小的线程。

在您的情况下,您应该使用Executors.newCachedThreadPool()。这个线程池没有固定的大小限制,这使得池可以同时运行所有的客户端。

英文:

> My question is, can I execute infinite amount Runnables depending on the Executors.newFixedThreadPool(x) or do they count as individual threads?

The thread pool with fixed size has internally a queue where tasks are queued. Each Runnable is put into that queue. A thread takes a new task from the queue if it has finished its current task.

There is no limit of tasks you can queue, except hardware limits. When you queue e.g. 20 tasks and have 10 threads in the pool, only 10 of those tasks, or rather Runnables, are executed. In your case, only x clients would be running because there are only x threads in the pool with fixed size.

You should use Executors.newCachedThreadPool() in your case. This thread pool doesn't have a limited size, which enables the pool to run all clients at the same time.

huangapple
  • 本文由 发表于 2020年5月19日 21:11:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/61891903.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定