首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何通过实现Runnable接口减少内存消耗?

如何通过实现Runnable接口减少内存消耗?
EN

Stack Overflow用户
提问于 2018-09-27 13:18:15
回答 2查看 166关注 0票数 0

在实现Runnable的类中,为了创建Thread,我们实例化Thread类,并通过传递Runnable对象来调用stating方法。为了创建两个线程,我们创建了两个Thread对象和Runnable对象。但是在case类扩展Thread类时,我们只为扩展Thread类的类创建了两个对象。

代码语言:javascript
复制
class ImplementsRunnable implements Runnable {


 private int counter = 0;

 public void run() {
 counter++;
 System.out.println("ImplementsRunnable : Counter : " + counter);
 }
 }

 class ExtendsThread extends Thread {

 private int counter = 0;

 public void run() {
 counter++;
 System.out.println("ExtendsThread : Counter : " + counter);
 }
 }

 public class ThreadVsRunnable {

 public static void main(String args[]) throws Exception {
 //Multiple threads share the same object.
 ImplementsRunnable rc = new ImplementsRunnable();
 Thread t1 = new Thread(rc);
 t1.start();
 Thread.sleep(1000); // Waiting for 1 second before starting next thread
 Thread t2 = new Thread(rc);
 t2.start();
 Thread.sleep(1000); // Waiting for 1 second before starting next thread
 Thread t3 = new Thread(rc);
 t3.start();

 //Creating new instance for every thread access.
 ExtendsThread tc1 = new ExtendsThread();
 tc1.start();
 Thread.sleep(1000); // Waiting for 1 second before starting next thread
 ExtendsThread tc2 = new ExtendsThread();
 tc2.start();
 Thread.sleep(1000); // Waiting for 1 second before starting next thread
 ExtendsThread tc3 = new ExtendsThread();
 tc3.start();
 }
 }
EN

回答 2

Stack Overflow用户

发布于 2018-09-27 17:11:50

注意:实例化Thread对象比实例化Runnable实例更耗费资源。在扩展Thread的基础上实现Runnable的思想是线程重用

从概念上讲,线程对象可以(同步)运行任意数量的任务(本例中为runanbles)。例如,这是由执行者利用的。

代码语言:javascript
复制
Executor executor = Executors.newFixedThreadPool(10);
for(int i = 0; i < 1000; i ++ ) {
     executor.execute(() -> System.out.println("test"));
}

在本例中,由10个线程组成的池运行1000个可运行代码。与扩展Thread相关的开销会增加您必须处理的任务越多(因此,尽管在您的示例中差异很小,但如果您必须运行10000个任务,则差异将变得非常明显)。

因此,实现Runnable而不是扩展Thread是一个很好的实践。

票数 2
EN

Stack Overflow用户

发布于 2018-09-27 17:58:02

当您构造Thread对象时,您所做的不仅仅是构造该对象。您还可以在JVM中分配一个线程,JVM通常使用操作系统API来执行此操作。操作系统线程比进程更便宜,但比大多数其他操作系统对象的重量级要大得多,因为每个线程都有自己的执行上下文,需要由内核处理。此外,每个线程都有自己的执行堆栈,必须为此分配空间。与新线程关联的实际内存分配超过1兆字节(!)在大多数Java实现上。相比之下,您的Runnable将只分配几个字节。

如果在应用程序的整个生命周期中重用线程来完成工作,那么内存成本就会分摊。更重要的是,设置新线程的CPU时间开销不为零(通常是syscall,这意味着至少有一次上下文切换,有时还会丢失当前线程的剩余部分)。与创建新线程相比,将新工作传递给已在运行的线程的工作量要小得多。

一个不错的经验法则是将java.lang (ThreadObject.wait)中公开的与并发相关的机制视为低级原语操作,而将java.util.concurrent中公开的API (ExecutorFuture等)作为更高级别的操作。低级机制(稍微)更灵活,但也更难正确使用。高级机制同样强大,但通常允许您在更高的抽象级别上思考问题,这通常会使您的程序更清晰、更正确。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52529875

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档