0

我将线程存储在容器中。随着时间的推移,这些线程中的一些会运行,而其中一些会死掉。我想要实现的是:自动(或定期)从容器中删除死(停止)线程。做这个的最好方式是什么?

编辑:我将线程存储在一个简单的链表中:

LinkedList<ServerThread> threadPool = new LinkedList<ServerThread>();

这个容器必须是动态的,因为随着时间的推移,我必须添加(并且显然是删除)线程。

EDIT2:这就是我目前管理线程的方式。正如你所看到的,我等待传入的连接,我不知道它什么时候会到达,但是当它到达时,我必须在一个新线程中处理它。

while (!interrupted()) {
            try {
                Socket clientSocket = serverSocket.accept();
                if (portNumber == Server.SMTP_PORT_NUMBER) {
                    threadPool.add(new SMTPThread(clientSocket, db));
                    threadPool.getLast().setName("SMTP Thread " + ++threadCounter);
                } else {
                    threadPool.add(new POP3Thread(clientSocket, db));
                    threadPool.getLast().setName("POP3 Thread " + ++threadCounter);
                }

                threadPool.get(threadPool.size() - 1).start();

            } catch (SocketTimeoutException e) {
            } catch (IOException ioe) {
            }
        }
4

2 回答 2

5

除非有特定原因,否则您不应维护自己的线程列表。我建议使用ExcecutorService自 Java 5 以来可用的优秀类。如下所示:

// create a thread pool with 10 workers
ExecutorService threadPool = Executors.newFixedThreadPool(10);
// or you can create an open-ended thread pool
// ExecutorService threadPool = Executors.newCachedThreadPool();
for (Job job : jobsToDo) {
    threadPool.submit(new MyJobProcessor(job));
}
// once we have submitted all jobs to the thread pool, it should be shutdown
threadPool.shutdown();
...
public class MyJobProcessor implements Runnable {
    private Job job;
    public MyJobProcessor(Job job) {
        this.job = job;
    }
    public void run() {
        // process the job
    }
}

线程池将负责维护池中正在运行的线程。线程将在下一个作业中重新使用,并且当池中没有更多作业并且它已被关闭时将被关闭。您不需要自己收获任何死线。


编辑

就您发布的代码而言,要从池中删除已完成的线程,您应该像这样运行它们:

 Iterator<ServerThread> iterator = threadPool.iterator();
 while (iterator.hasNext()) {
     ServerThread thread = iterator.next();
     if (!thread.isAlive()) {
        // remove it from the linked list
        iterator.remove();
     }
 }

每次向池中添加新线程后,我都会这样做。另外,请记住进行方法调用LinkedList效率不高。get(#)我建议您调整代码以执行以下操作:

            Socket clientSocket = serverSocket.accept();
            ServerThread serverThread;
            if (portNumber == Server.SMTP_PORT_NUMBER) {
                serverThread = new SMTPThread(clientSocket, db);
                serverThread.setName("SMTP Thread " + ++threadCounter);
            } else {
                serverThread = new POP3Thread(clientSocket, db);
                serverThread.setName("POP3 Thread " + ++threadCounter);
            }
            serverThread.start();
            threadPool.put(serverThread);
于 2012-05-23T16:46:21.283 回答
1

您可以使用 a来安排将在列表中运行并删除死线程Timer的周期。TimerTask这是一个草图:

static final List<Thread> threads = new LinkedList<Thread>();
static final Timer timer = new Timer(true);
public static void main(String[] args) {
  timer.scheduleAtFixedRate(new TimerTask() {public void run() {
    for (Iterator<Thread> it = threads.iterator(); it.hasNext();)
      if (!it.next().isAlive()) it.remove();
  }}, 0, 10000);
}
于 2012-05-23T16:42:45.270 回答