Java创建新执行线程有两种方法。一种方法是将类声明为 Thread
的子类。该子类应重写 Thread
类的run
方法。接下来可以分配并启动该子类的实例。
例如:
package lh.zjzk;
public class ThreadOne extends Thread {
@Override
public void run() {
for(int i = 0 ; i < 50;i++){
System.out.println("ThreadOne run"+i);
}
}
}
然后在主线程中调用他的start()方法来启动此线程。
package lh.zjzk;
/**
* 调用两个线程,其中一个输出A,两一个输出1
* @author Administrator
*
*/
public class ThreadDemo2 {
public static void main(String[] args) {
new ThreadOne().start();//
for(int i = 0 ; i < 50; i++){
System.out.println(i);
}
}
}
创建线程的另一种方法是声明实现 Runnable
接口的类。该类然后实现 run
方法。然后可以分配该类的实例,在创建Thread
时作为一个参数来传递并启动。
比如我们常见的卖票问题:
package lh.zjzk;
/**
* 此程序实现卖票
* @author Administrator
*
*/
public class ThreadDemo1 implements Runnable{
private int ticket =100;
@Override
public void run() {
while(true){
if(ticket >0)
System.out.println(Thread.currentThread().getName()+"还有"+(ticket--)+"张票");
else
break;
}
}
}
然后在调用它时,使用new Thread(Runnable target):
package lh.zjzk;
public class SaleTicket {
public static void main(String[] args) {
ThreadDemo1 th = new ThreadDemo1();
new Thread(th).start();//卖票线程1
new Thread(th).start();//卖票线程2
}
}
上面程序的关键之处在与,新建的两个线程的Runnable对象要是同一个对象,这样所有启动的线程执行的run()方法才会是同一个。比如:如果见SaleTicket类改成了
package lh.zjzk;
public class SaleTicket {
public static void main(String[] args) {
// ThreadDemo1 th = new ThreadDemo1();
// new Thread(th).start();//卖票线程1
// new Thread(th).start();//卖票线程2
//错误代码
new Thread(new ThreadDemo1()).start();//错误
new Thread(new ThreadDemo1()).start();//错误
}
此时运行时,就会出现每一个进程单独进行售票,比较两个代码可以发现,上面的Runnable对象不同,一种是两个线程运行同一个,而另一种则是没一次启动线程时,创建一个不同的Runnable对象。
线程的继承和实现的最大不同之处在与:使用实现方式避免了Java单继承的局限性,所以在定义线程时尽量使用实现方式。
比如:如果一个学生类,它有一段代码需要被多线程执行,但是它有一个父类Person,根据Java的单继承性,他就不能再继承Thread来实现代码共享,所以我们可以使用Runnable来实现它。