我试图找出使用executor (用于维护线程池)的普通多线程和多线程之间的性能差异。
下面是两者的代码示例。
没有执行程序代码的(带有多线程):
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryUsage;
import java.lang.management.ThreadMXBean;
import java.util.List;
public class Demo1 {
public static void main(String arg[]) {
Demo1 demo = new Demo1();
Thread t5 = new Thread(new Runnable() {
public void run() {
int count=0;
// Thread.State;
// System.out.println("ClientMsgReceiver started-----");
Demo1.ChildDemo obj = new Demo1.ChildDemo();
while(true) {
// System.out.println("Threadcount is"+Thread);
// System.out.println("count is"+(count++));
Thread t=new Thread(obj);
t.start();
ThreadMXBean tb = ManagementFactory.getThreadMXBean();
List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans();
for (MemoryPoolMXBean pool : pools) {
MemoryUsage peak = pool.getPeakUsage();
System.out.format("Peak %s memory used: %,d%n",
pool.getName(), peak.getUsed());
System.out.format("Peak %s memory reserved: %,d%n",
pool.getName(), peak.getCommitted());
}
System.out.println("Current Thread Count"+ tb.getThreadCount());
System.out.println("Peak Thread Count"+ tb.getPeakThreadCount());
System.out.println("Current_Thread_Cpu_Time "
+ tb.getCurrentThreadCpuTime());
System.out.println("Daemon Thread Count" +tb.getDaemonThreadCount());
}
// ChatLogin = new ChatLogin();
}
});
t5.start();
}
static class ChildDemo implements Runnable {
public void run() {
try {
// System.out.println("Thread Started with custom Run method");
Thread.sleep(100000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
System.out.println("A" +Thread.activeCount());
}
}
}
}带执行器的(多线程):
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryUsage;
import java.lang.management.ThreadMXBean;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Executor_Demo {
public static void main(String arg[]) {
BlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(10);
ThreadPoolExecutor executor = new ThreadPoolExecutor(
10, 100, 10, TimeUnit.MICROSECONDS, queue);
Executor_Demo demo = new Executor_Demo();
executor.execute(new Runnable() {
public void run() {
int count=0;
// System.out.println("ClientMsgReceiver started-----");
Executor_Demo.Demo demo2 = new Executor_Demo.Demo();
BlockingQueue<Runnable> queue1 = new ArrayBlockingQueue<Runnable>(1000);
ThreadPoolExecutor executor1 = new ThreadPoolExecutor(
1000, 10000, 10, TimeUnit.MICROSECONDS, queue1);
while(true) {
// System.out.println("Threadcount is"+Thread);
// System.out.println("count is"+(count++));
Runnable command= new Demo();
// executor1.execute(command);
executor1.submit(command);
// Thread t=new Thread(demo2);
// t.start();
ThreadMXBean tb = ManagementFactory.getThreadMXBean();
/* try {
executor1.awaitTermination(100, TimeUnit.MICROSECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} */
List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans();
for (MemoryPoolMXBean pool : pools) {
MemoryUsage peak = pool.getPeakUsage();
System.out.format("Peak %s memory used: %,d%n",
pool.getName(), peak.getUsed());
System.out.format("Peak %s memory reserved: %,d%n",
pool.getName(), peak.getCommitted());
}
System.out.println("daemon threads"+tb.getDaemonThreadCount());
System.out.println("All threads"+tb.getAllThreadIds());
System.out.println("current thread CPU time "
+ tb.getCurrentThreadCpuTime());
System.out.println("current thread user time "
+ tb.getCurrentThreadUserTime());
System.out.println("Total started thread count "
+ tb.getTotalStartedThreadCount());
System.out.println("Current Thread Count"+ tb.getThreadCount());
System.out.println("Peak Thread Count"+ tb.getPeakThreadCount());
System.out.println("Current_Thread_Cpu_Time "
+ tb.getCurrentThreadCpuTime());
System.out.println("Daemon Thread Count"
+ tb.getDaemonThreadCount());
// executor1.shutdown();
}
//ChatLogin = new ChatLogin();
}
});
executor.shutdown();
}
static class Demo implements Runnable {
public void run() {
try {
// System.out.println("Thread Started with custom Run method");
Thread.sleep(100000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
System.out.println("A" +Thread.activeCount());
}
}
}
}样本输出

当我运行这两个程序时,结果显示执行器比正常的多线程更昂贵。为什么会这样?
既然如此,遗嘱执行人到底有什么用?我们使用执行器来管理线程池。
我原以为执行者会给出比正常多线程更好的结果。
基本上,我是这样做的,因为我需要使用套接字编程和多线程处理数百万客户端。
任何建议都会有帮助。
发布于 2012-03-07 08:46:02
每个线程消耗堆栈的内存,从256 K到1M不等。您可以手动设置堆栈大小,但将其设置在128 K以下是危险的。因此,如果您有2G内存,并且可以在线程上花费1/2,那么您的线程就不会超过8K。如果这对您来说没有问题,那么使用普通的多线程处理(每个Runnable都有自己的堆栈)。如果您不愿意或不能为每个可运行程序花费这么多内存,请使用执行器。将线程池大小设置为处理器的数量(Runtime.availableProcessors()),或者更多。出现的主要问题是,您无法使Thread.sleep()或在您的运行中阻塞线程(例如,等待用户响应),因为这种阻塞实际上将线程排除在服务之外。因此,如果使用有限大小的线程池,就会出现所谓的“线程饥饿”,这实际上是一个死锁。如果线程池的大小是无限的,那么就会回到正常的多线程处理,很快就会耗尽内存。
解决方法是使用异步操作,即用回调设置一些请求,然后退出run()方法。然后,回调应该使用Executor.execute( Runnable )开始执行某个Runnable对象(可能是相同的),或者它可以执行runnable.run()本身的方法。
现在Java7 (nio2)中存在异步输入输出操作,但我未能使它服务于数百个网络连接。为了服务网络连接,可以使用异步网络库(例如Apache )。
组织回调和执行运行程序可能需要复杂的同步。为了使生活更容易,考虑使用Actor模型(http://en.wikipedia.org/wiki/Actor_model),其中Actor是一个可运行的运行程序,每次输入消息到达时都执行。存在许多Java库(例如https://github.com/rfqu/df4j)。
https://stackoverflow.com/questions/9597331
复制相似问题