Java平台从开始就被设计成为多线程环境。在你的主程序执行的时候,其它作业如碎片收集和事件处理则是在后台进行的。
本质上,你可以认为这些作业是线程。它们正好是系统管理线程,但是无论如何,它们是线程。线程使你能够定义相互独立的作业,彼此之间互不干扰。系统将交换这些作业进或出CPU,这样(从外部看来)它们好象是同时运行的。
在你需要在你的程序中处理多个作业时,你也可以使用多个进程。这些进程可以是你自己创建的,你也可以操纵系统线程。你进行这些多作业处理,要使用几个不同的类或接口:
java.util.Timer类
javax.swing.Timer类
Thread类
Runnable接口
对于简单的作业,通常需要重复的,你可以使用java.util.Timer类告诉它“每半秒钟做一次”。注意:大多数系统例程是使用毫秒的。半秒钟是500毫秒。
你希望Timer实现的任务是在java.util.TimerTask实例中定义的,其中运行的方法包含要执行的任务。这些在Hi类中进行了演示,其中字符串“Hi”重复地被显示在屏幕上,直到你按Enter键。
import java.util.*;
public class Hi
{
public static void main
(String args[])
throws java.io.IOException
{
TimerTask task = new TimerTask()
{
public void run()
{
System.out.println("Hi");
}
};
Timer timer = new Timer();
timer.schedule(task, 0, 500);
System.out.println
("Press ENTER to stop");
System.in.read(new byte[10]);
timer.cancel();
}
}
Java Runtime Environment工作的方式是只要有一个线程在运行,程序就不退出。这样,当取消被调用,没有其它线程在运行了,则程序退出。有一些系统线程在运行,如碎片收集程序。这些系统线程也被称为后台线程。后台线程的存在不影响运行环境被关闭,只有非后台线程保证运行环境不被关闭。
Javax.swing.Timer类与java.util.timer类的工作方式相似,但是有一些差别需要注意。第一,运行的作业被ActionListener接口的实现来定义。第二,作业的执行是在事件处理线程内部进行的,而不象java.util.Timer类是在它的外部。这是很重要的,因为它关系到Swing组件集是如何设计的。
如果你不熟悉Swing,它是一组可以被Java程序使用的图形组件。Swing被设计程被称为单线程的。这意味着对Swing类内部内容的访问必须在单个线程中完成。这个特定的线程是事件处理线程。
这样,例如你想改变Label组件的文字,你不能仅仅调用Jlabel的setText方法。相反,你必须确认setText调用发生在事件处理线程中,而这正是javax.swing.Time类派的上用场的地方。
为了说明这第二种情况,下面的程序显示一个增加的计数器的值。美半秒钟计数器的数值增加,并且新的数值被显示:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Count
{
public static void
main(String args[])
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation
(JFrame.EXIT_ON_CLOSE);
Container contentPane =
frame.getContentPane();
final JLabel label =
new JLabel("", JLabel.CENTER);
label.setFont(new Font
("Serif", Font.PLAIN, 36));
contentPane.add(label,
BorderLayout.CENTER);
ActionListener listener
= new ActionListener()
{
int count = 0;
public void actionPerformed
(ActionEvent e)
{
count++;
label.setText
(Integer.toString(count));
}
};
Timer timer = new Timer(500, listener);
timer.start();
frame.setSize(300, 100);
frame.show();
}
}
上述程序的结果是:
万一你要做的不是一个简单的重复作业,java.lang.Thread类就派上了用场。它允许你自己控制基本功能。通过创建Thread的一个子类,你可以使你的系统脱离,并进行一个长时间运行的作业,如从网络上读取一个文件,而不阻碍你的其它程序的运行。这种长时间运行的作业将在run方法中定义。
第二种方式是创建Thread类的子类并在子类中实现run方法,或在实现runnable的类中实现run方法,并将这个实现传递给Thread的构造函数。
你可能会问有什么区别。Java编程语言仅支持单一继承。如果你设计的调用是除了Thread以外的其它类,你可以是你的类实现Runnable,而它可以是你的作业被执行。否则,你定义Thread的子类来运行你的Run方法,在处理过程中不再添加其它操作。
对于创建Thread子类的第三种情况,下面的程序生成了一个新的线程来计算一个特定URL的字符数,这个URL是通过命令行传递进来的。在这进行过程之中,实现Runnable的第四种情况被演示,打印出重复的消息。
注意在实现Runnable的这后一种情况下,你必须提供重复消息的代码。你必须同时sleep,以分配时间并完成操作。在两种情况下,与使用Timer相比较。这段程序的最后一部分包含有你从命令行读取命令以触发程序结束。注意在系统读取URL并打印消息的同时,你总可以按Enter键结束程序。
import java.io.*;
import java.net.*;
public class Both
{
public static void
main(String args[])
{
final String urlString = args[0];
final String message = args[1];
Thread thread1 = new Thread()
{
public void run()
{
try
{
URL url = new URL(urlString);
URLConnection connection =
url.openConnection();
InputStreamReader isr = new
InputStreamReader(
connection.getInputStream());
BufferedReader reader =
new BufferedReader(isr);
int count = 0;
while (reader.read() != -1)
{
count++;
}
System.out.println("Size is : "
+ count);
reader.close();
} catch (MalformedURLException e)
{
System.err.println("Bad URL: "
+ urlString);
} catch (IOException e)
{
System.err.println
("I/O Problems");
}
}
};
thread1.start();
Runnable runnable = new Runnable()
{
public void run()
{
while(true)
{
System.out.println(message);
try
{
Thread.sleep(500);
} catch (InterruptedException e)
{
}
}
}
};
Thread thread2 = new Thread(runnable);
thread2.start();
try {
System.out.println
("Press ENTER to stop");
System.in.read(new byte[10]);
} catch (IOException e)
{
System.out.println("I/O problems");
}
System.exit(0);
}
}
因为有多种方式来处理线程,你选用哪种技术取决于你和你面临的条件。要成为一个有效的Java编程人员,尽管你通常不必学习Java编程语言的所有内容和核心库,但是线程是一个例外。你越早了解线程如何工作和如何使用线程,你将越早了解Java程序如何工作和交互。
分享到:
相关推荐
本案例将深入探讨Java多线程中的关键知识点,包括线程同步、线程通信和线程阻塞。 线程同步是为了防止多个线程同时访问共享资源,导致数据不一致。Java提供了多种同步机制,如synchronized关键字、Lock接口...
3. **线程通信**:`wait()`, `notify()` 和 `notifyAll()` 方法用于线程间的通信,但它们必须在`synchronized`代码块中使用,否则会抛出异常。 4. **线程状态**:Java线程有五种状态:新建、可运行、运行、阻塞和...
需要注意的是,直接调用`run()`方法并不会启动一个新的线程,而是在当前线程中执行该方法。 #### Java多线程在网络编程中的应用 Java在网络编程方面表现出了极强的能力,尤其是在处理并发连接方面。下面通过开发一...
Java应用开发多线程是Java编程中的重要领域,它涉及到如何在单个程序中同时执行多个任务,以提高系统效率和资源利用率。对于初学者来说,理解并掌握Java多线程是进阶到更复杂系统设计的关键步骤。下面将详细阐述Java...
Java多线程是Java编程中的重要概念,尤其在开发高效能和并发应用程序时不可或缺。本文将深入探讨Java多线程的应用实例,这对于初学者来说是一个很好的学习起点。 首先,我们来看"SimulateRailwayStation.java"这个...
Java应用开发教程主要涵盖的是Java语言在实际应用中的开发技术和方法,这包括了Java的基础语法、面向对象编程、异常处理、集合框架、多线程、网络编程等方面的知识。同时,结合"java数据库服务器程序设计"这个标签,...
Java的线程工具易于使用,并且像Java中的其他东西一样可以在不同的平台之间移植。这是一件好事,因为如果没有线程,那么除了最简单的applet之外,几乎不可能编写出任何程序。如果你想使用Java,就必须学习线程。 ...
- Applet的生命周期包括init(), start(), paint(), stop(), destroy()等方法,这些方法可能在不同的线程中被调用,因此要确保线程安全。 - Applet需要在浏览器环境中运行,其安全性受到限制,不能直接访问本地文件...
Java多线程是Java编程中的一个重要概念...在实际开发中,应根据具体需求选择合适的线程模型和同步机制,以达到最佳的并发性能。同时,理解并熟练掌握多线程编程能帮助开发者解决复杂的问题,提高软件的质量和用户体验。
此外,`jstack`工具是Java开发工具集(JDK)的一部分,它能以命令行形式输出JVM中线程的详细堆栈跟踪信息,这对于远程服务器上的应用非常有用。在命令行中运行`jstack <pid>`(pid是Java进程的ID),即可查看该进程...
为了在多线程中同步进度更新,我们可以利用synchronized关键字、wait()、notify()方法,或者使用Java并发库中的高级工具,如Semaphore、CyclicBarrier或CountDownLatch等。 一个简单的进度条实现可以采用共享变量...
多线程技术是Java高级程序语言解决并发处理问题的核心方案,在网络通信系统设计和开发中扮演着关键角色。本文将深入探讨多线程技术在网络通信系统中应用的基本原理、实现机制以及安全性与同步控制的策略。 首先,要...
在Java编程语言中,多线程是其核心特性之一,它允许程序同时执行多个任务,提高了应用程序的效率和响应性。本示例着重探讨如何在Java中实现多线程,并通过一个具体的小球运动模拟来阐述相关概念。 一、多线程基础 ...
Java是一种分布式的编程语言,能够借助Java虚拟机在不同的硬件和操作系统上运行,这使得Java应用几乎可以无限制地在所有平台上运行。这种跨平台的特性极大地推动了Java编程语言的广泛应用。 在计算机软件开发过程中...
在Java开发中,Swing作为构建桌面应用程序图形用户界面(GUI)的主要工具之一,其设计目标是为了提供一个强大、灵活且易于使用的框架。Swing允许开发者轻松创建自定义组件或通过扩展现有组件来实现功能,这为程序的...
若在网络连接等可能引起阻塞的操作中使用主线程,会导致程序无响应,因此通常会创建新的线程来处理这些操作,以保持用户界面的交互性。例如,一个简单的"Echo Message"应用可能会创建一个新的线程来处理网络通信,...
Java线程分析是Java开发中的重要环节,尤其是在处理性能优化、死锁排查或者并发问题时。TDA(Thread Dump Analyzer)是一款强大的Java线程分析工具,它能够帮助开发者深入理解应用在运行时的线程状态,包括线程的...
Java 模拟线程并发是编程领域中的一个重要概念,尤其在多核处理器和高并发应用中,理解并熟练掌握线程并发技术对于提升程序性能至关重要。在Java中,线程并发可以通过多种方式实现,包括继承Thread类、实现Runnable...
在多线程环境中,为了保证数据一致性,防止资源竞争,开发者可能会使用`synchronized`关键字、`java.util.concurrent.locks`包中的锁机制,或者`java.util.concurrent`包中的其他并发工具类,如`CountDownLatch`、`...
#### 四、线程在Java UI开发中的应用 - **事件驱动模型**:Java中的GUI框架如AWT和Swing采用了事件驱动模型,其中有一个专门的事件线程负责处理用户的输入事件。为了避免事件处理导致UI卡顿,通常会将耗时的操作放...