Java 单镜头背景线,避免加入?

Java 单镜头背景线,避免加入?,java,multithreading,Java,Multithreading,简单的问题是,此代码是否有效,并且不会留下任何类型的资源泄漏: // code... final int delaySecs = 60; new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(delaySecs * 1000); // code to do

简单的问题是,此代码是否有效,并且不会留下任何类型的资源泄漏:

    // code...
    final int delaySecs = 60;
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                Thread.sleep(delaySecs * 1000);
                // code to do whatever delayed single-shot action
            } catch (InterruptedException ex) { /* skip action */ }
        }
    }).start();
    // more code...
如果无效,我是否应该使用像这样的
Thread
子类来启用
setDaemon(true)
调用:

class DaemonThread extends Thread {
    public DaemonThread(Runnable target) {
        super(target);
        setDaemon(true);
    }
}

或者别的什么?

为什么不实例化
线程
,在其上调用
setDaemon()
,然后通过
start()
调用呢?我认为您不需要
线程
子类

e、 g


最好的方法是将应该执行的任何逻辑包装到Runnable中,并将执行留给ExecutorService

如果出现以下情况,执行器将负责停止/重用线程

MyRunnable runnable = new MyRunnable();
ExecutorService executor = Executors.newFixedThreadPool(1);   
executor.execute(runnable);

这样,您就可以将程序逻辑与执行/生命周期管理分开。执行器还能够处理线程内的异常/中断。这将允许您在不打开新线程的情况下重新启动后台逻辑。

自1.5版起,Java就为您的用例提供了特定的支持,因此建议您使用它:

ScheduledExecutorService s = Executors.newScheduledThreadPool(1);
s.schedule(new Runnable() { ...my task, no Thread.sleep()... },
   1, TimeUnit.MINUTES);
s.shutdown();

这样既可以实现适当的延迟,又可以在之后进行清理。

是的,如果只使用一次,则更可取。我想我将从question的
类DaemonThread
中删除
private
,使其更合理地抽象。+1用于消除显式睡眠。否则,我更喜欢没有临时变量的解决方案,比如这里的
s
,这是否可能
ScheduledExecutorService
?因为
ScheduledFuture
的返回类型是
ScheduledFuture
,一个允许您监视和控制计划任务进度的句柄对象,所以不可能将其变成一行。但无论如何,这是Java的标准。我通常会不假思索地提取一个方法,在本例中是一个接受可运行和时间延迟的方法。因此,目前,这看起来是我在问题中所写的最有希望的替代方法:启动包含延迟的线程,然后清理“触发并忘记”。我仍然想知道的是,如果在我的问题代码中,
setDaemon(true)是必需的,或者如果GC将收集未连接、未引用的线程……当然,如果睡眠时间长,不执行
setDaemon
将减慢应用程序关闭,但这是另一个问题。如果没有
setDaemon(true)
,并且使用显式
Thread.sleep
方法,在延迟到期和任务执行之前,应用程序不会关闭。另一方面,一旦作业完成,线程就会死亡,所有内容都会被清除。
Executors.newSingleThreadExecutor().execute(newrunnable(){…})似乎也能工作,从文档来看,它似乎还允许实现自行决定重用线程;它不会重用线程,因为您的一行程序每次都会创建一个新的执行器,而不会关闭它。这是一个资源泄漏,与您自己的示例相反,在您的示例中,线程在其
运行
方法完成时死亡。@MarkoTopolnik-Bah,所以它。。。“我想我也不接受这个答案了,很抱歉点了303号。”海德,注意下面讨论的那句诱人的一句话:。
ScheduledExecutorService s = Executors.newScheduledThreadPool(1);
s.schedule(new Runnable() { ...my task, no Thread.sleep()... },
   1, TimeUnit.MINUTES);
s.shutdown();