为什么线程创建被认为是一个昂贵的过程?
为什么线程创建被认为是一个昂贵的过程?
我正在阅读有关线程池的内容,发现线程创建被认为是一个昂贵的过程。这与我的直觉相反,于是我决定进行测试:
public static void main(String[] args) { long start = System.currentTimeMillis(); for (int i = 0; i < 1000; i++) { new Thread(new Runnable() { @Override public void run() { } }).start(); } long end = System.currentTimeMillis(); System.out.println(end - start + "ms"); }
在我的系统上,这将打印出696ms
。因此,创建一个线程的时间接近0.69毫秒。为什么被认为是慢的呢?
编辑:
public class Test { static int a = 1; static long start; static void setA() { ++a; if(a>=1000) { long end = System.currentTimeMillis(); System.out.println(end - start + "ms"); } } public static void main(String[] args) { start = System.currentTimeMillis(); for (int i = 0; i <= 1000; ++i) { new Thread(new Runnable() { @Override public void run() { setA(); } }).start(); } } }
这将打印出729ms
。
线程创建被认为是一个昂贵的过程,主要有以下几个原因:首先,start方法调用了一个本地方法,而本地调用总是很慢。其次,创建线程是一个内核函数(为其分配内存,将其添加到调度程序),因此程序必须等待线程实际被创建。
这解释了线程的内部工作方式,但不解释为什么0.72毫秒的线程被认为是慢的。
嗯,一般来说并不认为它很慢,但您必须注意您创建线程的目的。例如,如果没有真正必要,仅仅为了将计算运行在多线程中而创建线程是没有意义的。
您能引用一些证明本地方法调用很慢的统计数据吗?JVM经常进行本地调用,所以我不认为这是正确的。
调用本身是“慢”的,因为VM在调用方法之前必须执行一些步骤:在VM堆栈上创建一个本地帧,在本地帧上将由调用本地方法的Java代码推送的参数作为本地引用添加,还要将这些值推送到本地堆栈上,调用本地方法,清理堆栈,然后释放带有本地引用的本地VM帧。这个消息来源于我和我的一个朋友正在开发的一个VM。
因此,为了避免线程创建的昂贵过程,可以使用线程池来重复使用线程,从而减少线程创建的次数。
线程创建被认为是一个昂贵的过程,原因是每次在程序中创建一个线程时,虚拟机(VM)和操作系统都需要分配一系列的数据结构来跟踪线程的执行和上下文切换。例如,每个线程都有自己的堆栈、局部变量、线程局部变量等。如果是绿色线程,则虚拟机将分配和管理这些数据结构。如果是本地线程,则操作系统将管理它们。无论哪种情况,都需要分配系统资源来管理线程。这就是为什么创建线程需要一些时间,并且创建大量线程可能会消耗大量系统资源的原因。
解决方法之一是使用线程池。线程池可以在应用程序启动时创建一组线程,并将它们保存在池中以供重复使用。这样可以避免频繁创建和销毁线程的开销,提高了线程的复用性和效率。
以下是一个使用Java线程池的示例代码:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPoolExample { public static void main(String[] args) { // 创建一个线程池,最多同时执行两个线程 ExecutorService executor = Executors.newFixedThreadPool(2); // 提交任务给线程池 executor.submit(new MyTask()); executor.submit(new MyTask()); executor.submit(new MyTask()); // 关闭线程池 executor.shutdown(); } static class MyTask implements Runnable { @Override public void run() { // 执行任务的代码 System.out.println("Executing task..."); } } }
通过使用线程池,我们可以控制线程的数量,避免创建过多的线程导致资源耗尽。线程池可以重用线程,从而减少了线程创建和销毁的开销,提高了程序的性能和响应速度。
总之,线程创建被认为是一个昂贵的过程,因为需要分配和管理大量的数据结构和系统资源。使用线程池可以有效地管理线程,并提高程序的效率和性能。