2012-08-31 110 views
0

我有1个线程谁唯一的工作就是抓住DatagramPackets关闭套接字,并在缓冲区中把它们粘。另一个线程处理该缓冲区,处理DatagramPackets。我想有一个线程池在这个缓冲区中工作。Java的线程池多个相同任务

我曾想过使用一个固定的线程池来做到这一点。为此,我是否需要创建池,然后提交足够的可运行子进行执行以填充它?我曾希望有一种方式来说“这是我希望你执行的线程/可运行,这是我想要运行多少,GO!”。有这样的方法吗?除了固定线程池之外的东西更适合吗?

回答

1

当您使用ExecutorService时,您将Runnable作业提交给由池中的线程依次运行的线程池。你可以做下列之一:

  1. 让每个Runnable坐在一个循环,在循环来处理每一个数据包从一个BlockingQueue出队。这可能比它们全部在缓冲区对象周围同步更容易。喜欢的东西:

    public void run() { 
        while (!shutdown) { 
         packet = packetQueue.take(); 
         processPacket(packet); 
        } 
    } 
    
  2. 或者,可以将每个数据包提交到线程池的工作本身虽然可能会增加你的目标负载。您可以处理每个数据包,提取有效负载,并使用处理负载的run()方法在负载周围创建Runnable包装。在Runnable类的内容会是这样的:

    Payload payload; 
    public void run() { 
        // process packet here 
        processPayload(payload); 
    } 
    

使用这两种机制,我会选择最适合自己的处理器的数量和处理任务的性质相匹配的固定线程号。下面的例子使用了处理器的数量,但您可能想要关闭一些GC或其他任务。如果其他IO上的处理块可能需要更多。只有性能测试才会告诉你最佳值是什么。

// start a pool that uses the number of threads that there are processors 
ExecutorService threadPool = Executors.newFixedThreadPool(
    Runtime.getRuntime().availableProcessors()); 
+0

#1似乎违背了线程池的精神 - 将工作单元调度到最多N个线程池。相反,您要旋转所有N个线程(其中N =最大池大小),并且每个线程都在队列中等待并等待队列,直到工作进入。如果这样做,您可以直接创建N个线程并跳过线程池完全。 – JimN

+1

还有一件事 - 按照书面的说法,#1的关闭策略并不完全正常,因为线程可能会永远在包队列中等待,并且从不重新检查“关闭”并终止。在这种情况下,我通常使用“毒丸”方法来表示线程应该终止。 – JimN

+1

真的任何需要线程的任务都会通过线程池@Jim得到改进。即使在#1的情况下。 – Gray

1

Executors.newFixedThreadPool创建工作得很好的固定线程池。

实施的内部语义是这样的线程池,将优先考虑创建一个新的线程,直到达到其首选大小(核心池大小),这似乎是你想要的。