Java线程创建性能与C#线程创建性能与C++;(本机线程)? 我感兴趣的是爪哇、C和C++中线程创建的实际成本是多少?我知道,当线程创建一组操作时,必须完成:分配线程堆栈,初始化描述符,等等。
但我对实际成本很感兴趣。C++和java使用不同的VM和不同的JIT,C++执行本地代码。所以线程创建时间在所有这些语言中都是不同的。我还听说Java中的线程创建要比C#慢得多。有人能就这个问题给出权威性的答案和解释吗?在C#、Java和Visual C++中对10000个线程的创建进行基准测试: C#Java线程创建性能与C#线程创建性能与C++;(本机线程)? 我感兴趣的是爪哇、C和C++中线程创建的实际成本是多少?我知道,当线程创建一组操作时,必须完成:分配线程堆栈,初始化描述符,等等。,c#,java,c++,multithreading,performance,C#,Java,C++,Multithreading,Performance,但我对实际成本很感兴趣。C++和java使用不同的VM和不同的JIT,C++执行本地代码。所以线程创建时间在所有这些语言中都是不同的。我还听说Java中的线程创建要比C#慢得多。有人能就这个问题给出权威性的答案和解释吗?在C#、Java和Visual C++中对10000个线程的创建进行基准测试: C# 类程序 { 静态void Main(字符串[]参数) { 秒表=新秒表(); watch.Start(); 对于(int i=0;i
类程序
{
静态void Main(字符串[]参数)
{
秒表=新秒表();
watch.Start();
对于(int i=0;i<10000;i++)
{
螺纹=新螺纹(无螺纹);
thread.Start();
}
看,停;
控制台写入线(手表已过);
}
静态空洞不存在()
{
//无所事事
}
}
结果:1.7638042秒
JAVA
公共级螺纹加工机{
公共静态void main(字符串[]args){
Runnable r=新的Runnable(){
公开募捐{
//无所事事
}
};
long startTime=System.nanoTime();
对于(int i=0;i<10000;i++){
螺纹=新螺纹(r);
thread.start();
}
长停止时间=System.nanoTime();
长总时间=停止时间-开始时间;
系统输出打印(总时间);
}
}
结果:1.514557805秒(或1514557805纳秒)
Visual C++
DWORD WINAPI DoNothing(LPVOID lpParam)
{
返回0;
}
void main()
{
HANDLE-ourThreadHandle=0;
系统时间st1;
系统时间st2;
int i;
GetLocalTime(&st1);
对于(i=0;i<10000;i++){
ourThreadHandle=CreateThread(NULL,0,DoNothing,0,0,NULL);
}
GetLocalTime(&st2);
双dblSt1=st1.wssecond+(st1.wmillisonds/1000);
双dblSt2=st2.wssecond+(st2.wmill seconds/1000);
双结果=dblSt2-dblSt1;
coutC++通常是一种运行速度更快的语言,尽管它可能是一种更难学习的语言;因此,理解更多的基本函数需要更长的时间,这可能会减慢在创建应用程序时对其进行编码的过程
创建新线程时,它与其他线程共享其代码段、数据段和操作系统资源,如打开的文件。但它被分配自己的堆栈、寄存器集和程序计数器
线程成本
线程在内存使用和性能方面对程序(和系统)有实际的成本。每个线程都需要在内核内存空间和程序内存空间中分配内存
管理线程和协调其调度所需的核心结构使用有线内存存储在内核中。线程的堆栈空间和每线程数据存储在程序的内存空间中
这些结构中的大多数都是在首次创建时创建和初始化的
创建线程—一个相对昂贵的进程,因为
所需的与内核的交互
其中一些成本是可配置的,例如为次线程分配的堆栈空间量。创建线程的时间成本是一个粗略的近似值,应仅用于相互之间的相对比较。线程创建时间可能因处理器负载、计算机速度和线程数量的不同而有很大差异可用的系统和程序存储器
线程不消耗内存(除了它们的堆栈,这是
恒定大小);进程消耗内存。整个线程点
它们共享进程状态
公共语言运行时(CLR)线程的堆栈空间设置为
(由CLR指定)每个默认值为1MB(对于64位代码线程为4MB)
C++中,它为栈保留1MB(映射其地址空间),但不一定分配在物理内存中,只有较小的一部分。如果堆栈增长超过页面错误,分配更多物理内存。
Java线程创建成本很高,因为其中涉及到相当多的工作:
- 必须为线程堆栈分配和初始化一大块内存
- 需要进行系统调用以在主机操作系统中创建/注册本机线程
- 描述符需要创建、初始化并添加到JVM内部数据结构中
另外,只要线程处于活动状态,它就会占用资源,这也是非常昂贵的;例如,线程堆栈、可从堆栈访问的任何对象、JVM线程描述符、操作系统本机线程描述符。一般来说,权威的答案是“如果线程创建是应用程序中的瓶颈,那么您就做错了”。您不应该频繁地创建和销毁线程,这会产生任何影响。如果您有许多短期任务频繁启动和停止,请使用线程池。@jalf:有时您需要在按顺序执行两个任务和以新线程的形式启动第二个任务之间进行选择,这样它就不会阻塞当前线程或成为一个整体被第一个任务吓坏了。你感兴趣的是哪一个任务完成得最快,哪一个CPU利用得最好。了解启动新线程的成本可以帮助你做出决定。@RalphChapin请重新阅读我的评论。我没有说“按顺序做每件事”,我说过你可以并行运行它们,而不必为每个任务启动新线程。这就是线程池的用途。你可以通过
class Program
{
static void Main(string[] args)
{
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 0; i < 10000; i++)
{
Thread thread = new Thread(DoNothing);
thread.Start();
}
watch.Stop();
Console.WriteLine(watch.Elapsed);
}
static void DoNothing()
{
//Do Nothing
}
}
public class ThreadBencher {
public static void main(String[] args) {
Runnable r = new Runnable() {
public void run() {
//Do nothing
}
};
long startTime = System.nanoTime();
for (int i = 0; i < 10000; i++) {
Thread thread = new Thread(r);
thread.start();
}
long stopTime = System.nanoTime();
long totalTime = stopTime - startTime;
System.out.print(totalTime);
}
}
DWORD WINAPI DoNothing( LPVOID lpParam )
{
return 0;
}
void main()
{
HANDLE ourThreadHandle = 0;
SYSTEMTIME st1;
SYSTEMTIME st2;
int i;
GetLocalTime(&st1);
for (i = 0; i < 10000; i++) {
ourThreadHandle = CreateThread( NULL, 0, DoNothing, 0, 0, NULL);
}
GetLocalTime(&st2);
double dblSt1 = st1.wSecond + (st1.wMilliseconds / 1000);
double dblSt2 = st2.wSecond + (st2.wMilliseconds / 1000);
double result = dblSt2 - dblSt1;
cout << st1.wSecond << "." << st1.wMilliseconds << endl;
cout << st2.wSecond << "." << st2.wMilliseconds << endl;
}