Welcome 微信登录

首页 / 软件开发 / JAVA / Java:无处不在的线程

Java:无处不在的线程2011-06-11谁创建线程?

即使您从未显式地创建一个新线程,您仍可能会发现自己在使用线程。线程被从各种来源中引入到我们的程序中。

有许多工具可以为您创建线程,如果要使用这些工具,应该了解线程如何交互,以及如何防止线程互相干扰。

AWT 和 Swing

任何使用 AWT 或 Swing 的程序都必须处理线程。AWT 工具箱创建单个线程,用于处理 UI 事件,任何由 AWT 事件调用的事件侦听器都在 AWT 事件线程中执行。

您不仅必须关心同步对事件侦听器和其它线程之间共享的数据项的访问,而且还必须找到一种方法,让由事件侦听器触发的长时间运行任务(如在大文档中检查拼写或在文件系统中搜索一个文件) 在后台线程中运行,这样当该任务运行时,UI 就不会停滞了(这可能还会阻止用户取消操作)。这样做的一个好的框架示例是 SwingWorker 类(请参阅参考资料)。

AWT 事件线程并不是守护程序线程;这就是通常使用 System.exit() 结束 AWT 和 Swing 应用程序的原因。

使用 TimerTask

JDK 1.3 中,TimerTask 工具被引入到 Java 语言。这个便利的工具让您可以稍后在某个时间执行任务(例如,即从现在起十秒后运行一次任务),或者定期执行任务(即,每隔十秒运行任务)。

实现 Timer 类非常简单:它创建一个计时器线程,并且构建一个按执行时间排序的等待事件队列。

TimerTask 线程被标记成守护程序线程,这样它就不会阻止程序退出。

因为计时器事件是在计时器线程中执行,所以必须确保正确同步了针对计时器任务中使用的任何数据项的访问。

在 CalculatePrimes 示例中,并没有让主线程休眠,我们可以使用 TimerTask,方法如下:

public static void main(String[] args) {
Timer timer = new Timer();

final CalculatePrimes calculator = new CalculatePrimes();
calculator.start();
timer.schedule(
new TimerTask() {
public void run()
{
calculator.finished = true;
}
}, TEN_SECONDS);
}

servlet 和 JavaServer Pages 技术

servlet 容器创建多个线程,在这些线程中执行 servlet 请求。作为 servlet 编写者,您不知道(也不应该知道)您的请求会在什么线程中执行;如果同时有多个对相同 URL 的请求入站,那么同一个 servlet 可能会同时在多个线程中是活动的。

当编写 servlet 或 JavaServer Pages (JSP) 文件时,必须始终假设可以在多个线程中并发地执行同一个 servlet 或 JSP 文件。必须适当同步 servlet 或 JSP 文件访问的任何共享数据;这包括 servlet 对象本身的字段。