Java编程中实现多线程应用有两种途径,一中是创建用户自己的线程子类,一中是在用户自己的类中实现Runnable接口,无论那种方法,都需要使用Thread类极其方法。
1.Runnable接口
Runnable接口只有一个方法run(),所有实现Runnable接口的用户类都必须具体实现这个方法,为他书写方法体并定义具体操作。当线程被调度并转入运行状态时,它所执行的就是run()方法中规定的操作。所以,一个实现了Runnable接口的类实际上定义了一个主线程之外的新线程的操作。
2.Thread类
Thread类综合了Java程序中一个线程需要拥有一下属性和方法。
⑴构造函数
Thread类的构造函数有多个,常用的有如下两种:
①public Thread;
创建一个系统线程类的对象。
②public Thread(Runnable target,String name)
创建一个新的线程对象,新线程的名字由参数name决定,新线程的run()方法就是target对象的run()方法。target是一个实现了Runnable接口的类对象,而实现了Runnable接口的类必须为接口声明run()方法编写代码。
⑵Thread类的主要方法
①启动线程的start()方法
start()方法将启动线程对象,使之从新建状态转入就绪状态并进入就绪队列排队。
②定义线程操作的run()方法
Thread类的run()方法与Runnable接口中的run()方法的功能和作用相同,都用来定义线程对象被调度之后的操作,都是系统自动调用而用户程序不得引用的方法。系统的Thread类中,run()方法没有具体类容,所有用户需要创建自己的Thread类的子类来定义新的run()方法来覆盖原来的run()方法。
③sleep()方法——线程休眠
优先级高的线程可以在它的run()方法中调用sleep()方法来使自己放弃处理器资源,休眠一段时间。休眠事件的长短由sleep()方法的参数决定。例如:
sleep(int millsecond);//millsecond是以毫秒为单位的休眠时间
④isAlive()方法
该方法用于判断线程是否消亡,如消亡则返回false,存活则返回true。在用stop()方法终止一个线程之前,最好先用isAlive方法检查线程是否存活,撤销不存在的线程可能会造成系统错误。
⑤currentThread方法
该方法是Thread类的一个静态方法,它返回当前线程对象(对象的引用)。
⑥getName方法
返回当前对象的名称。
3.如何在程序中实现多线程
用户需要创建自己的Thread类的子类,并在子类中重新定义自己的run()方法,这个润方法中包含了用户线程的操作。这样在用户需要创建自己的线程时,只需要创建一个已定义好的Thread类的事例就可以了。
import java.io.*;
public class TestThread {
public static void main(String args[]) {
if(args.length<1){
//要求用户输入一个命令行。否则程序无法进行下去
System.out.println("请输入一个命令行参数");
System.exit(0);}
//创建用户Thread子类的对象实例,使其处于NewBorn状态
PrimeThread subthread=new PrimeThread(Integer.parseInt(args[0]));
subthread.start();
while(subthread.isAlive()&&subthread.readyToGoOn()){
System.out.println("Couting the prime number.....\n");//说明主线程在运行
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO: handle exception
return;
}
}//While循环结束
System.out.println("按任意键继续。。。");
try {
System.in.read();
} catch (IOException e) {
// TODO: handle exception
}
}//main方法结束
}//主类结束
class PrimeThread extends Thread{
boolean m_bContinue=true;//标志本线程是否继续
int m_nCircleNum; //循环的上限
PrimeThread(int Num){ //构造函数
m_nCircleNum=Num;
}
boolean readyToGoOn(){
return(m_bContinue);
}
@Override
public void run() {
// TODO Auto-generated method stub
int number=3;
boolean flag=true;
while(true){ //无限循环
for(int i=2;i<number;i++) //检查number是否为素数
if(number%i==0)
flag=false;
if(flag) //打印该数是否为素数的信息
System.out.println(number+"是素数");
else
System.out.println(number+"不是素数");
number++; //修改number数值,为下一轮素数检查做准备
if(number>m_nCircleNum) //到达要求检查数值的上限
{
m_bContinue=false; //准备结束此线程
return; //结束run()方法,接受线程
}
flag=true; //恢复flag,准备下一个number
try{
sleep(500);
}
catch(InterruptedException e){
return;
}
}//whlie循环结束
}//run方法结束
}//primeThread定义类结束
⑵实现Runnable接口
在这个途径中,已经有了一个父类的用户类可以听过实现Runnable接口的方法来定义用户线程的操作。Runnable接口只有一个方法Run(),实现这个接口,就必须定义Run()方法中的具体内容,用户新建线程的操作也可以有这个方法来决定。定义好Run()方法之后,当用户需要建立新的线程时,只要以这个实现了Run()方法的类的对象为参数创建系统类Thread对象,就可以把用户实现的Run()方法借用过来。
下面是听过实现Runnable接口来实现多线程的例子:
import java.applet.Applet;
import java.awt.Label;
import java.awt.TextField;
public class UseRunnable extends Applet implements Runnable{
Label prompt1=new Label("第一个子线程"); //标签一
Label prompt2=new Label("第二个子线程"); //标签二
TextField threadFirst=new TextField(14); //显示线程被调度次数的文本框
TextField threadSecond=new TextField(14); //显示线程被调度次数的文本框
Thread Thread1,Thread2; //两个Thread线程对象
int count1=0,count2=0; //两个计数器
@Override
public void init() {
// TODO Auto-generated method stub
add(prompt1);
add(threadFirst);
add(prompt2);
add(threadSecond);
}
@Override
public void start() {
// TODO Auto-generated method stub
Thread1=new Thread(this,"FirstThread"); //
Thread2=new Thread(this,"SecondThread"); //
Thread1.start(); //
Thread2.start();
}
@Override
public void run() {//实现Runnable接口的run()方法,在线程启动后自动执行
// TODO Auto-generated method stub
String currentRunning;
while(true){
try {
Thread.sleep((long) (Math.random()*3000));//使当前线程休眠0到3秒
} catch (InterruptedException e) {}
// TODO: handle exception
currentRunning=Thread.currentThread().getName();
if(currentRunning.equals("FirstThread")){
count1++;
threadFirst.setText("线程1第"+count1+"次被调度");
}
else if(currentRunning.equals("SecondThread")){
count2++;
threadSecond.setText("线程2第"+count2+"次被调度");
}
}
}
}