在特定的秒数之后运行一个函数

我找到了 javax.swing.timer,但是我真的不知道如何使用它。看起来我正在寻找比这个类提供的更简单的方法。

请添加一个简单的用法示例。

301862 次浏览
new java.util.Timer().schedule(
new java.util.TimerTask() {
@Override
public void run() {
// your code here
}
},
5000
);

编辑:

你可以这样做:

if($(selector).filter('.class1, .class2').length){
// Or logic
}


if($(selector).filter('.class1.class2').length){
// And logic
}
, 五千

Javadoc 说:

);

编辑:

Javadoc 说:

在对 Timer 对象的最后一次实时引用消失并且所有未完成的任务都已完成执行之后,计时器的任务执行线程将优雅地终止(并且成为垃圾收集的对象)。然而,这可能需要任意长的时间才能发生。

JQuery

if( ['class', 'class2'].some(c => [...element[0].classList].includes(c)) )

记住,完成后关闭遗嘱执行人很重要。当最后一个任务完成时,shutdown()方法将干净利落地关闭线程池,并将阻塞直到发生这种情况。shutdownNow()将立即终止线程池。

我只是注意到,对于我的实现,我依赖于 id的异步调用。如果我需要在 hasClasses改变 id的同时通过 id 查询元素,那么我可能会导致一个问题。

为了规避这个问题,我们只需要添加一个唯一的 uuid属性(字面意思就是 uuid)。

这里有一个更正:

$.fn.extend({
hasClasses: function (selectors) {
// Setup
const uuid = generateUUID(); // Create new uuid to query later
$(this).attr(uuid, "");      // Apply uuid to element for query


// Query to find if element has any of the classes
const res = selectors.some(cls => !!$(`[${uuid}].${cls}`).length);


// Remove the uuid attribute
$(this).removeAttr(uuid);


// Done
return res;
}
})

在几个简单的句子中,什么是 Java类加载器,什么时候使用,为什么使用?

如果元素有 id而不是添加 attribute,我们仍然可以使用它。
我不确定查询 id是否更快。我引用了 这个,但是从它的外观来看,现代浏览器并没有太大的成功。如果存在 id而不是 attribute,仍然可以使用它来实现。

阅读 Swing 教程中关于“ 如何使用计时器”的部分以获得更多信息。

摘自太阳 教程:

动机

将代码组合成可执行本机代码的过程称为链接——将单独编译的代码与共享库代码合并以创建可执行应用程序。这在诸如 Java 之类的动态编译编程语言中是不同的。在爪哇。Java 编译器生成的类文件保持原样,直到加载到 Java 虚拟机(JVM)中——换句话说,链接过程在运行时由 JVM 执行。根据需要将类加载到 JVM 中。当一个已加载的类依赖于另一个类时,那么该类也会被加载。

使用静态编译的编程语言(如 C 和 C + +)编写的应用程序被编译成本机特定指令,并保存为可执行文件。将代码组合成可执行本机代码的过程称为链接——将单独编译的代码与共享库代码合并以创建可执行应用程序。这在诸如 Java 之类的动态编译编程语言中是不同的。在爪哇。Java 编译器生成的类文件保持原样,直到加载到 Java 虚拟机(JVM)中——换句话说,链接过程在运行时由 JVM 执行。根据需要将类加载到 JVM 中。当一个已加载的类依赖于另一个类时,那么该类也会被加载。

启动 Java 应用程序时,要运行的第一个类(或应用程序的入口点)是具有名为 main ()的公共静态 void 方法的类。此类通常具有对其他类的引用,并且所有加载引用类的尝试都由类加载器执行。

启动 Java 应用程序时,要运行的第一个类(或应用程序的入口点)是具有名为 main ()的公共静态 void 方法的类。此类通常具有对其他类的引用,并且所有加载引用类的尝试都由类加载器执行。

要了解这种递归类装入以及一般类装入思想,请考虑以下简单类:

public class HelloApp {
public static void main(String argv[]) {
System.out.println("Aloha! Hello and Bye");
}
}

要了解这种递归类装入以及一般类装入思想,请考虑以下简单类:

public class HelloApp {
public static void main(String argv[]) {
System.out.println("Aloha! Hello and Bye");
}
}

如果您运行这个指定-verose: class 命令行选项的类,以便它打印正在加载的类,您将获得如下输出。注意,这只是部分输出,因为列表太长,无法在这里显示。

prmpt>java -verbose:class HelloApp






[Opened C:\Program Files\Java\jre1.5.0\lib\rt.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\jsse.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\jce.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\charsets.jar]
[Loaded java.lang.Object from shared objects file]
[Loaded java.io.Serializable from shared objects file]
[Loaded java.lang.Comparable from shared objects file]
[Loaded java.lang.CharSequence from shared objects file]
[Loaded java.lang.String from shared objects file]
[Loaded java.lang.reflect.GenericDeclaration from shared objects file]
[Loaded java.lang.reflect.Type from shared objects file]
[Loaded java.lang.reflect.AnnotatedElement from shared objects file]
[Loaded java.lang.Class from shared objects file]
[Loaded java.lang.Cloneable from shared objects file]
[Loaded java.lang.ClassLoader from shared objects file]
[Loaded java.lang.System from shared objects file]
[Loaded java.lang.Throwable from shared objects file]
.
.
.
[Loaded java.security.BasicPermissionCollection from shared objects file]
[Loaded java.security.Principal from shared objects file]
[Loaded java.security.cert.Certificate from shared objects file]
[Loaded HelloApp from file:/C:/classes/]
Aloha! Hello and Bye
[Loaded java.lang.Shutdown from shared objects file]
[Loaded java.lang.Shutdown$Lock from shared objects file]

如果您运行这个指定-verose: class 命令行选项的类,以便它打印正在加载的类,您将获得如下输出。注意,这只是部分输出,因为列表太长,无法在这里显示。

prmpt>java -verbose:class HelloApp






[Opened C:\Program Files\Java\jre1.5.0\lib\rt.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\jsse.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\jce.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\charsets.jar]
[Loaded java.lang.Object from shared objects file]
[Loaded java.io.Serializable from shared objects file]
[Loaded java.lang.Comparable from shared objects file]
[Loaded java.lang.CharSequence from shared objects file]
[Loaded java.lang.String from shared objects file]
[Loaded java.lang.reflect.GenericDeclaration from shared objects file]
[Loaded java.lang.reflect.Type from shared objects file]
[Loaded java.lang.reflect.AnnotatedElement from shared objects file]
[Loaded java.lang.Class from shared objects file]
[Loaded java.lang.Cloneable from shared objects file]
[Loaded java.lang.ClassLoader from shared objects file]
[Loaded java.lang.System from shared objects file]
[Loaded java.lang.Throwable from shared objects file]
.
.
.
[Loaded java.security.BasicPermissionCollection from shared objects file]
[Loaded java.security.Principal from shared objects file]
[Loaded java.security.cert.Certificate from shared objects file]
[Loaded HelloApp from file:/C:/classes/]
Aloha! Hello and Bye
[Loaded java.lang.Shutdown from shared objects file]
[Loaded java.lang.Shutdown$Lock from shared objects file]

如您所见,首先加载应用程序类(HelloApp)所需的 Java 运行时类。

如您所见,首先加载应用程序类(HelloApp)所需的 Java 运行时类。

Java2平台中的类装入器

Java2平台中的类装入器

Java 编程语言不断发展,使应用程序开发人员的日常生活变得更加轻松。这是通过提供 API 来实现的,这些 API 允许您专注于业务逻辑而不是基本机制的实现细节,从而简化了您的生活。为了反映 Java 平台的成熟度,最近将 J2SE 1.5更改为 J2SE 5.0,这一点很明显。

Java 编程语言不断发展,使应用程序开发人员的日常生活变得更加轻松。这是通过提供 API 来实现的,这些 API 允许您专注于业务逻辑而不是基本机制的实现细节,从而简化了您的生活。为了反映 Java 平台的成熟度,最近将 J2SE 1.5更改为 J2SE 5.0,这一点很明显。

从 JDK 1.2开始,内置在 JVM 中的引导类装入器负责装入 Java 运行时的类。这个类装入器只装入在引导类路径中找到的类,由于这些类是受信任的类,验证过程不会像对待不受信任的类那样执行。除了引导类装入器之外,JVM 还有一个负责从标准扩展 API 装入类的扩展类装入器,以及一个从通用类路径和应用程序类装入类的系统类装入器。

从 JDK 1.2开始,内置在 JVM 中的引导类装入器负责装入 Java 运行时的类。这个类装入器只装入在引导类路径中找到的类,由于这些类是受信任的类,验证过程不会像对待不受信任的类那样执行。除了引导类装入器之外,JVM 还有一个负责从标准扩展 API 装入类的扩展类装入器,以及一个从通用类路径和应用程序类装入类的系统类装入器。

因为有不止一个类装入器,所以它们在根是引导类装入器的树中表示。每个类装入器都有一个对其父类装入器的引用。当一个类装入器被要求装入一个类时,它会在尝试装入项目本身之前咨询它的父类装入器。父节点依次咨询其父节点,依此类推。所以只有在所有的祖先类装入器都找不到类之后,当前的类装入器才会涉及到。换句话说,使用委托模型。

ClassLoader 类

因为有不止一个类装入器,所以它们在根是引导类装入器的树中表示。每个类装入器都有一个对其父类装入器的引用。当一个类装入器被要求装入一个类时,它会在尝试装入项目本身之前咨询它的父类装入器。父节点依次咨询其父节点,依此类推。所以只有在所有的祖先类装入器都找不到类之后,当前的类装入器才会涉及到。换句话说,使用委托模型。

java.lang.ClassLoader是一个抽象类,可以被需要扩展 JVM 动态加载类的方式的应用程序子类化。java.lang.ClassLoader(及其子类)中的构造函数允许您在实例化新的类装入器时指定父类。如果没有显式地指定父类,那么虚拟机的系统类装入器将被指定为默认的父类。换句话说,ClassLoader 类使用委托模型来搜索类和资源。因此,ClassLoader 的每个实例都有一个关联的父类装入器,这样当请求查找类或资源时,任务在尝试查找类或资源本身之前就被委托给其父类装入器。ClassLoader 的 loadClass()方法在调用加载类时按顺序执行以下任务:

ClassLoader 类

java.lang.ClassLoader是一个抽象类,可以被需要扩展 JVM 动态加载类的方式的应用程序子类化。java.lang.ClassLoader(及其子类)中的构造函数允许您在实例化新的类装入器时指定父类。如果没有显式地指定父类,那么虚拟机的系统类装入器将被指定为默认的父类。换句话说,ClassLoader 类使用委托模型来搜索类和资源。因此,ClassLoader 的每个实例都有一个关联的父类装入器,这样当请求查找类或资源时,任务在尝试查找类或资源本身之前就被委托给其父类装入器。ClassLoader 的 loadClass()方法在调用加载类时按顺序执行以下任务:

如果类已经被加载,它将返回它。

如果类已经被加载,它将返回它。 否则,它将对新类的搜索委托给父类装入器。 否则,它将对新类的搜索委托给父类装入器。 如果父类装入器没有找到该类,则 loadClass()调用方法 findClass()来查找并装入该类。 如果父类装入器没有找到该类,则 loadClass()调用方法 findClass()来查找并装入该类。 如果父类装入器没有找到该类,则 finalClass()方法在当前类装入器中搜索该类。


如果父类装入器没有找到该类,则 finalClass()方法在当前类装入器中搜索该类。


原始文章中还有更多内容,它还向您展示了如何实现您自己的网络类加载器,从而回答了您为什么(以及如何)这样做的问题。参见 API 文件

问题是“为什么一个人

使用 javax.swing.Timer的示例

Timer timer = new Timer(3000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
// Code to be executed
}
});
timer.setRepeats(false); // Only execute once
timer.start(); // Go go go!

这段代码只执行一次,执行时间为3000毫秒(3秒)。

这个 ClassLoader 类存在”?

嗯,主要是为了在事情出错的时候能够修复它们: ——)。

正如 camickr 提到的,您应该查找“ 如何使用摆动计时器”以获得简短的介绍。

这是真的,只要你只是编写一个应用程序,编译它到一个 JAR,可能包括一些额外的库 JAR,你不需要知道类装入器,它只是工作。

当它们运行时,您需要知道类装入器如何决定何时装入它们。

还有. . 如何在实践中使用它?

尽管如此,了解一点类装入器和类装入对于更好地理解幕后发生的情况仍然很有帮助。例如,“静态初始化器”将在加载类时运行,因此要理解它们何时运行,您需要知道类加载器如何决定何时加载它们。

还有. . 如何在实践中使用它?

对于简单的情况,你不需要它们。但是,如果您需要在运行时动态加载代码,并且明确控制代码的来源(例如,通过网络加载,在编译时加载插件不可用,等等) ,那么您可能需要做更多的工作。然后你可以写你自己的类装入器。有关链接,请参见其他答案。

我的代码如下:

new java.util.Timer().schedule(


new java.util.TimerTask() {
@Override
public void run() {
// your code here, and if you have to refresh UI put this code:
runOnUiThread(new   Runnable() {
public void run() {
//your code


}
});
}
},
5000
);

对于简单的情况,你不需要它们。但是,如果您需要在运行时动态加载代码,并且明确控制代码的来源(例如,通过网络加载,在编译时加载插件不可用,等等) ,那么您可能需要做更多的工作。然后你可以写你自己的类装入器。有关链接,请参见其他答案。

ScheduledThreadPoolExecutor 有这个能力,但它是相当重量级的。

Long left ToSleep = request + delayMillis-System.currentTimeMillis () ;

Timer 也有这个能力,但打开几个线程,即使只使用一次。

如果(left ToSleep > 0){ Sleep (left to Sleep) ; }

下面是一个简单的测试实现(签名接近于 Android 的 Handler.postDelayed ()) :

public class JavaUtil {
public static void postDelayed(final Runnable runnable, final long delayMillis) {
final long requested = System.currentTimeMillis();
new Thread(new Runnable() {
@Override
public void run() {
// The while is just to ignore interruption.
while (true) {
try {
long leftToSleep = requested + delayMillis - System.currentTimeMillis();
if (leftToSleep > 0) {
Thread.sleep(leftToSleep);
}
break;
} catch (InterruptedException ignored) {
}
}
runnable.run();
}
}).start();
}
}

测试:

@Test
public void testRunsOnlyOnce() throws InterruptedException {
long delay = 100;
int num = 0;
final AtomicInteger numAtomic = new AtomicInteger(num);
JavaUtil.postDelayed(new Runnable() {
@Override
public void run() {
numAtomic.incrementAndGet();
}
}, delay);
Assert.assertEquals(num, numAtomic.get());
Thread.sleep(delay + 10);
Assert.assertEquals(num + 1, numAtomic.get());
Thread.sleep(delay * 2);
Assert.assertEquals(num + 1, numAtomic.get());
}
public static Timer t;


public synchronized void startPollingTimer() {
if (t == null) {
TimerTask task = new TimerTask() {
@Override
public void run() {
//Do your work
}
};


t = new Timer();
t.scheduleAtFixedRate(task, 0, 1000);
}
}
断裂; } catch (InterruptedException 忽略){

作为@tanens 回答的一种变体: 如果您不能等待垃圾收集器清理您的线程,那么取消 run 方法结束时的计时器。

Timer t = new java.util.Timer();
t.schedule(
new java.util.TimerTask() {
@Override
public void run() {
// your code here
// close the thread
t.cancel();
}
},
5000
);
} }

所有其他解答器都需要在新线程中运行代码。 Run () ; } 在一些简单的用例中,您可能只想稍等一下,然后在同一个线程/流中继续执行。

}) start () ; }

下面的代码演示了这种技术。请记住,这类似于 java.util。计时器在引擎盖下面,但更轻量级。

import java.util.concurrent.TimeUnit;
public class DelaySample {
public static void main(String[] args) {
DelayUtil d = new DelayUtil();
System.out.println("started:"+ new Date());
d.delay(500);
System.out.println("half second after:"+ new Date());
d.delay(1, TimeUnit.MINUTES);
System.out.println("1 minute after:"+ new Date());
}
}
}

测试:

@Test
public void testRunsOnlyOnce() throws InterruptedException {
long delay = 100;
int num = 0;
final AtomicInteger numAtomic = new AtomicInteger(num);
JavaUtil.postDelayed(new Runnable() {
@Override
public void run() {
numAtomic.incrementAndGet();
}
}, delay);
Assert.assertEquals(num, numAtomic.get());
Thread.sleep(delay + 10);
Assert.assertEquals(num + 1, numAtomic.get());
Thread.sleep(delay * 2);
Assert.assertEquals(num + 1, numAtomic.get());
}
= System.currentTimeMillis () ;

实现

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;


public class DelayUtil {
/**
*  Delays the current thread execution.
*  The thread loses ownership of any monitors.
*  Quits immediately if the thread is interrupted
*
* @param duration the time duration in milliseconds
*/
public void delay(final long durationInMillis) {
delay(durationInMillis, TimeUnit.MILLISECONDS);
}


/**
* @param duration the time duration in the given {@code sourceUnit}
* @param unit
*/
public void delay(final long duration, final TimeUnit unit) {
long currentTime = System.currentTimeMillis();
long deadline = currentTime+unit.toMillis(duration);
ReentrantLock lock = new ReentrantLock();
Condition waitCondition = lock.newCondition();


while ((deadline-currentTime)>0) {
try {
lock.lockInterruptibly();
waitCondition.await(deadline-currentTime, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
} finally {
lock.unlock();
}
currentTime = System.currentTimeMillis();
}
}
}
是) 类永远不会被未经授权的代码攻击。

类装入器是 JVM 的一个函数组件,它从’。类的文件或通过网络进入堆中的方法区域。

详情请参阅 给你

看起来像是 JVM 不可分割的一部分,但是作为一个最终的 java 用户,我为什么要担心呢?原因如下:

我认为在这种情况下:

import javax.swing.*;
import java.awt.event.ActionListener;

每个类装入器都有自己的名称空间,特定类装入器调用的类进入它的名称空间。

是最好的。当问题阻止 Ui 堆栈或在繁重的工作或网络调用之前不可见的进度时。我们可以使用以下方法(根据我的经验) :

由两个不同的类加载器调用的类彼此之间不具有可见性,从而增强了安全性。

1秒后运行一个方法:

 public static void startMethodAfterOneSeconds(Runnable runnable) {
Timer timer = new Timer(1000, new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent e) {
runnable.run();
}


});
timer.setRepeats(false); // Only execute once
timer.start();
}

类装入器父子委托机制确保 javaapi 类永远不会被未经授权的代码破解。

在 n 秒后运行一次方法,不要重复:

public static void startMethodAfterNMilliseconds(Runnable runnable, int milliSeconds) {
Timer timer = new Timer(milliSeconds, new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent e) {
runnable.run();
}


});
timer.setRepeats(false); // Only execute once
timer.start();
}

详情请参阅 给你

在 n 秒后运行一个方法,然后重复:

 public static void repeatMethodAfterNMilliseconds(Runnable runnable, int milliSeconds) {
Timer timer = new Timer(milliSeconds, new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent e) {
runnable.run();
}


});
timer.setRepeats(true); // Only execute once
timer.start();
}
克:

public static void startMethodAfterNMilliseconds(Runnable runnable, int milliSeconds) {
Timer timer = new Timer(milliSeconds, new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent e) {
runnable.run();
}


});
timer.setRepeats(false); // Only execute once
timer.start();
}

在 n 秒后运行一个方法,然后重复:

 public static void repeatMethodAfterNMilliseconds(Runnable runnable, int milliSeconds) {
Timer timer = new Timer(milliSeconds, new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent e) {
runnable.run();
}


});
timer.setRepeats(true); // Only execute once
timer.start();
}

用法:

 startMethodAfterNMilliseconds(new Runnable() {
@Override
public void run() {
// myMethod(); // Your method goes here.
}
}, 1000);