Java平台从开始就被设计成为多线程环境在你的主程序执行的时候其它作业如碎片收集和事件处理则是在后台进行的
本质上你可以认为这些作业是线程它们正好是系统管理线程但是无论如何它们是线程线程使你能够定义相互独立的作业彼此之间互不干扰系统将交换这些作业进或出CPU这样(从外部看来)它们好象是同时运行的
在你需要在你的程序中处理多个作业时你也可以使用多个进程这些进程可以是你自己创建的你也可以操纵系统线程你进行这些多作业处理要使用几个不同的类或接口
javautilTimer类
javaxswingTimer类
Thread类
Runnable接口
对于简单的作业通常需要重复的你可以使用javautilTimer类告诉它每半秒钟做一次注意大多数系统例程是使用毫秒的半秒钟是毫秒
你希望Timer实现的任务是在javautilTimerTask实例中定义的其中运行的方法包含要执行的任务这些在Hi类中进行了演示其中字符串Hi重复地被显示在屏幕上直到你按Enter键
import javautil*;
public class Hi
{
public static void main
(String args[])
throws javaioIOException
{
TimerTask task = new TimerTask()
{
public void run()
{
Systemoutprintln(Hi);
}
};
Timer timer = new Timer();
timerschedule(task );
Systemoutprintln
(Press ENTER to stop);
Systeminread(new byte[]);
timercancel();
}
}
Java Runtime Environment工作的方式是只要有一个线程在运行程序就不退出这样当取消被调用没有其它线程在运行了则程序退出有一些系统线程在运行如碎片收集程序这些系统线程也被称为后台线程后台线程的存在不影响运行环境被关闭只有非后台线程保证运行环境不被关闭
JavaxswingTimer类与javautiltimer类的工作方式相似但是有一些差别需要注意第一运行的作业被ActionListener接口的实现来定义第二作业的执行是在事件处理线程内部进行的而不象javautilTimer类是在它的外部这是很重要的因为它关系到Swing组件集是如何设计的
如果你不熟悉Swing它是一组可以被Java程序使用的图形组件Swing被设计程被称为单线程的这意味着对Swing类内部内容的访问必须在单个线程中完成这个特定的线程是事件处理线程
这样例如你想改变Label组件的文字你不能仅仅调用Jlabel的setText方法相反你必须确认setText调用发生在事件处理线程中而这正是javaxswingTime类派的上用场的地方
为了说明这第二种情况下面的程序显示一个增加的计数器的值美半秒钟计数器的数值增加并且新的数值被显示:
import javaxswing*;
import javaawt*;
import javaawtevent*;
public class Count
{
public static void
main(String args[])
{
JFrame frame = new JFrame();
framesetDefaultCloseOperation
(JFrameEXIT_ON_CLOSE);
Container contentPane =
framegetContentPane();
final JLabel label =
new JLabel( JLabelCENTER);
labelsetFont(new Font
(Serif FontPLAIN ));
contentPaneadd(label
BorderLayoutCENTER);
ActionListener listener
= new ActionListener()
{
int count = ;
public void actionPerformed
(ActionEvent e)
{
count++;
labelsetText
(IntegertoString(count));
}
};
Timer timer = new Timer( listener);
timerstart();
framesetSize( );
frameshow();
}
}
上述程序的结果是
万一你要做的不是一个简单的重复作业javalangThread类就派上了用场它允许你自己控制基本功能通过创建Thread的一个子类你可以使你的系统脱离并进行一个长时间运行的作业如从网络上读取一个文件而不阻碍你的其它程序的运行这种长时间运行的作业将在run方法中定义
第二种方式是创建Thread类的子类并在子类中实现run方法或在实现runnable的类中实现run方法并将这个实现传递给Thread的构造函数
你可能会问有什么区别Java编程语言仅支持单一继承如果你设计的调用是除了Thread以外的其它类你可以是你的类实现Runnable而它可以是你的作业被执行否则你定义Thread的子类来运行你的Run方法在处理过程中不再添加其它操作
对于创建Thread子类的第三种情况下面的程序生成了一个新的线程来计算一个特定URL的字符数这个URL是通过命令行传递进来的在这进行过程之中实现Runnable的第四种情况被演示打印出重复的消息
注意在实现Runnable的这后一种情况下你必须提供重复消息的代码你必须同时sleep以分配时间并完成操作在两种情况下与使用Timer相比较这段程序的最后一部分包含有你从命令行读取命令以触发程序结束注意在系统读取URL并打印消息的同时你总可以按Enter键结束程序
import javaio*;
import *;
public class Both
{
public static void
main(String args[])
{
final String urlString = args[];
final String message = args[];
Thread thread = new Thread()
{
public void run()
{
try
{
URL url = new URL(urlString);
URLConnection connection =
urlopenConnection();
InputStreamReader isr = new
InputStreamReader(
connectiongetInputStream());
BufferedReader reader =
new BufferedReader(isr);
int count = ;
while (readerread() != )
{
count++;
}
Systemoutprintln(Size is :
+ count);
readerclose();
} catch (MalformedURLException e)
{
Systemerrprintln(Bad URL:
+ urlString);
} catch (IOException e)
{
Systemerrprintln
(I/O Problems);
}
}
};
threadstart();
Runnable runnable = new Runnable()
{
public void run()
{
while(true)
{
Systemoutprintln(message);
try
{
Threadsleep();
} catch (InterruptedException e)
{
}
}
}
};
Thread thread = new Thread(runnable);
threadstart();
try {
Systemoutprintln
(Press ENTER to stop);
Systeminread(new byte[]);
} catch (IOException e)
{
Systemoutprintln(I/O problems);
}
Systemexit();
}
}
因为有多种方式来处理线程你选用哪种技术取决于你和你面临的条件要成为一个有效的Java编程人员尽管你通常不必学习Java编程语言的所有内容和核心库但是线程是一个例外你越早了解线程如何工作和如何使用线程你将越早了解Java程序如何工作和交互