1.线程实现方法
即实现runnable接口或者继承thread类,由于java是单继承机制,所以一般采用实现runnable接口的方法。
public class LiftOff implements Runnable {
protected int countDown = 10;
private static int taskCount = 0;
private final int id = taskCount++;
public LiftOff() {
}
public LiftOff(int countDown) {
this.countDown = countDown;
}
public String status() {
return "#" + id + "(" + (countDown > 0 ? countDown : "LiftOff!") + "),";
}
public void run() {
while (countDown-- > 0) {
System.out.println(status());
Thread.yield();//暂停当前正在执行的线程对象,并执行其他线程。试图让其它线程运行,但根本无法保证这一点
/*
* try { TimeUnit.MILLISECONDS.sleep(100);//进入阻塞,休眠 } catch
* (InterruptedException e) { e.printStackTrace(); }
*/
}
}
public static void main(String[] args) {
// 纯粹的直接调用,与线程无关。不过实际上仍然使用了线程,即分配给main函数的线程,但火箭本身没有开线程
LiftOff lift = new LiftOff();
// lift.run();
// 新开的单独火箭发射线程,同时主线程仍在跑,与火箭线程竞争,本例"Waiting for LiftOff"反而先打印输出
Thread t = new Thread(new LiftOff());
// t.start();
// System.out.println("Waiting for LiftOff");
for (int i = 0; i < 5; i++) {
new Thread(new LiftOff()).start();
System.out.println("Waiting for LiftOff");
}
以上即线程的基本实现方法,需注意的是,直接调用run方法不过是一次普通的方法调用,用thread调用start方法才能开启一个线程。因为线程是有一整个生命周期的,与直接调用方法不同。
在上面例子中,各个liftoff所在线程实际上都是由主线程main创建,但除此之外它们并没有其他关系。它们都会无差别的竞争资源,运行程序可以看出,输出语句"Waiting for LiftOff"虽然看起来在线程启动后运行,但却在其前面或中间均有输出,说明启动的线程和主线程在相互竞争。
由此也可以证明仅有main线程一个用户线程执行完毕,不能决定JVM是否退出,也即是说main线程并不一定是最后一个退出的线程。此前曾看到一个问题,如何在main方法运行完毕后继续执行某段程序,答案就是在main方法中新开一个线程单独去执行。