有没有C++ Java 中的析构函数等效吗?

发布于 2024-11-19 00:18:31 字数 521 浏览 2 评论 0原文

最简单的设计如下:

class Session {
  Timer t = new Timer();
  // ...
};

每当分配 Session 时,我都会在其中启动一个计时器;计时器将在 10-20 分钟后到期。现在,假设 Session 在计时器到期之前被销毁;那么这是我必须停止计时器的情况。我不知道是否有最后一个方法在 Session 被销毁时总是被调用。

Java 中是否有某种相当于 C++ 析构函数的东西,可以帮助我在 Session 被销毁时 cancel() 计时器? (无需等待 GC)

编辑:请不要重新标记 C++。我想要类似的东西。 Session 是一个电话会话,当连接到它的所有用户都断开连接时,该会话就会被销毁。现在,没有最后调用的 Session 方法,也没有任何异常。

In simplest form, following is the design:

class Session {
  Timer t = new Timer();
  // ...
};

Whenever, Session is allocated, I start a timer inside it; the timer will be expired after 10-20 mins. Now, suppose if Session is destroyed before the timer can expire; then it's a scenario where I must stop timer. I don't know if is there any last method which is always called when Session is destroyed.

Is there some sort of C++ destructor equivalent in Java, which help me to cancel() the timer when Session is destroyed ? (without waiting for GC)

Edit: Please don't retag for C++. I wanted something of that equivalent. The Session is a phone session which is get destroyed when all the user connected to it are disconnected. Now, there is no Session method which is called lastly nor there is any exception.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

花开雨落又逢春i 2024-11-26 00:18:31

不,Java 中没有内置这样的东西。最接近的是编写一个终结器,但不能保证它会运行。

Session是如何被销毁的?如果有调用的方法,请务必将代码放在那里。

如何创建会话?如果您在 try/catch 块中执行此操作,则可以清理 finally 块中的所有内容。

我会编写一个 close() 方法来处理它并在 finally 块中调用它。

No, there's no such thing built into Java. The closest is to write a finalizer, but there's no guarantee that it'll run.

How is a Session destroyed? If there's a method called, by all means put the code there.

How do you create a Session? If you do it within a try/catch block, you can clean up everything in a finally block.

I would write a close() method that took care of it and call it in a finally block.

二智少女 2024-11-26 00:18:31

与 C++ 不同,您无法控制 Java 中的对象释放 - 也就是说,GC 在认为合适的时候收集对象,只是保证它不会收集在给定时间范围内的任何引用可以到达的任何对象。

Object.finalize(),它充当执行清理的最后机会钩子,但运行时根本不保证它会被调用。

我会重新考虑设计并尝试想出一种更明确的方法来清理计时器。

Unlike C++, you cannot control object deallocation in Java - that is, the GC collects objects whenever it sees fit, merely guaranteeing that it won't collect anything that can be reached through any reference that is in scope at a given time.

There is Object.finalize(), which acts as a last-chance hook to do cleanup, but the runtime does not guarantee that it gets called at all.

I'd rethink the design and try to come up with a more explicit way of cleaning up your timers.

悲喜皆因你 2024-11-26 00:18:31

在 Java 中,变量并不像在 C++ 中那样直接表示对象 - Java 中的变量是对对象的引用。因此,对象不能超出范围 - 只有引用对象的变量才能超出范围。

您可以重写 Finalize(),它是 Object 类中的一个方法,当垃圾收集器要永久丢弃对象时会调用该方法,但这与析构函数并不完全相同。请参阅 Object 类中的 Finalize() 方法的 API 文档。

In Java, variables do not directly represent objects like they do in C++ - variables in Java are references to objects. So an object cannot go out of scope - only a variable that refers to an object can go out of scope.

You can override finalize(), which is a method in class Object that is called by the garbage collector when it is about to permanently discard an object, but that's not exactly the same as a destructor. See the API documentation of the finalize() method in class Object.

亽野灬性zι浪 2024-11-26 00:18:31

首先,finalize相当于析构函数。不要尝试将其作为一个整体来使用;这是行不通的。 Java 中没有为此构建任何内容,但在某些圈子中,有一个约定使用 void dispose() 来实现此目的;您可以编写 ptr.dispose(),而不是 delete ptr;。 (当然,内存稍后会被回收。)在这种情况下,最好还定义 finalize,以便在 dispose< 之前回收对象时生成某种内部错误。 /code> 被调用。

First, finalize is not the equivalent of a destructor. Don't try and use it as one; it won't work. There is nothing built into Java for this, but in some circles, there is a convention to use void dispose() for this; instead of delete ptr;, you write ptr.dispose(). (The memory, of course, gets reclaimed later.) In such cases, it's a good idea to also define finalize, to generate some sort of internal error if the object is reclaimed before dispose is called.

菊凝晚露 2024-11-26 00:18:31

大多数时候,您可以构建问题,因此不需要析构函数。

为每个Session创建一个Timer是比较重的。您最好向 ScheduledExecutorService 提交延迟任务。通过使其重量轻,就没有必要取消它。 (事实上​​,cancel() 不会删除它,它被标记为不运行)

在这种情况下,为了简单起见,您可以使用单例 ScheduledExecutorService。

class Session {
    private static final ScheduledExecutorService timer = 
                                    Executors.newSingleThreadScheduledExecutor();
    private Future<Void> timeoutFuture = null;

    // call every time you want the timeout to start from now.
    public void resetTimer() {
        if(timeoutFuture != null) timeoutFuture.cancel(false);
        timeoutFuture = timer.schedule(new Callable<Void>() {
            public Void call() {
                sessionTimedOut();
                return null;
            }
        }, TIMEOUT_SECONDS, TimeUnit.SECONDS);
    }

    void sessionTimedOut() {
        // what to do when the session times out.
    }
}

这里昂贵的组件 ScheduledExecutorService 被创建一次并在应用程序的生命周期内存在。当 Session 被清理(且任务已过期)时,Future 被丢弃

Most of the time you can structure the problem so you don't need a destructor.

Creating a Timer for each Session is relatively heavy weight. You are better off submitting a delay task to a ScheduledExecutorService. By making it light weight there would be no need to cancel it. (In fact cancel() doesn't remove it, it is flagged not to run)

You can have a singleton ScheduledExecutorService for simplicty in this case.

class Session {
    private static final ScheduledExecutorService timer = 
                                    Executors.newSingleThreadScheduledExecutor();
    private Future<Void> timeoutFuture = null;

    // call every time you want the timeout to start from now.
    public void resetTimer() {
        if(timeoutFuture != null) timeoutFuture.cancel(false);
        timeoutFuture = timer.schedule(new Callable<Void>() {
            public Void call() {
                sessionTimedOut();
                return null;
            }
        }, TIMEOUT_SECONDS, TimeUnit.SECONDS);
    }

    void sessionTimedOut() {
        // what to do when the session times out.
    }
}

Here the expensive component, the ScheduledExecutorService is created once and lives for the life of the application. The Future is discarded when the Session is cleaned up (and the task has expired)

你丑哭了我 2024-11-26 00:18:31

java中没有这样的方法。当对象被垃圾收集器销毁时,可能会调用在顶级 Object 中定义的 finalize() 方法,但这不是您可以执行的行为依靠。

您能做的最好的事情就是将对象设置为 null(删除引用),这将使其为垃圾回收做好准备。

There is not a method like that in java. The finalize() method, defined in the top-level Object, may be invoked when the object is being destroyed by the garbage collector, but this is not a behavior you can rely upon.

The best you can do is just set the object to null (removes the reference), which will make it ready for garbage collection.

枕花眠 2024-11-26 00:18:31

您可以使用 CDI(上下文依赖注入) - 例如 Weld,或者在某些 JEE 服务器(TomEE、JBoss 等)上运行程序。下面是一个使用数据库的示例。

根据您的喜好,在您的类上使用适当的 @...Scoped (ApplicationScoped、SessionScoped 等)注释,例如:

@ApplicationScoped
public class MyDatabaseFactory implements Serializable {}

在用 @PostConstruct 注释的某些方法的构造函数中执行您想要执行的操作

@PostConstruct
private void initializeObjectsOrConnections() {
  // ...
}

使用 @Inject 注释将您的对象注入到其他位置(如果您愿意):

public class MyApplication {

  @Inject
  MyDatabaseFactory databaseFactory;

  // ...
}

清理、销毁对象并断开与数据库的连接 - 您想在 C++ 的析构函数中在注释的方法中执行的操作和MyDatabaseFactory 类的 @PreDestroy,例如:

@PreDestroy
private void destroyObjectsOrCloseConnections() {
  // ...
}

使用起来非常简单,我们在 Java 中拥有相当于 C++ 中的析构函数。

You may use CDI (Context Dependency Injection) - such as Weld for example or run the program on some JEE server (TomEE, JBoss etc.). Below you have an example of working with databases.

Use appropriate @...Scoped (ApplicationScoped, SessionScoped etc.) annotation on your class, as you prefer eg.:

@ApplicationScoped
public class MyDatabaseFactory implements Serializable {}

Do what you wanted to do in constructor in some method annotated with @PostConstruct:

@PostConstruct
private void initializeObjectsOrConnections() {
  // ...
}

Inject your object with @Inject annotation to other places (if you want to):

public class MyApplication {

  @Inject
  MyDatabaseFactory databaseFactory;

  // ...
}

Cleanup, destroy objects and disconnect from database - what you wanted to do in destructor from C++ in method annotated with @PreDestroy of MyDatabaseFactory class, eg.:

@PreDestroy
private void destroyObjectsOrCloseConnections() {
  // ...
}

It is very simple to use and we have in Java equivalent of destructor from C++.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文