-
线程入门 —— 使用Runnable接口创建一个子类,具体查看下述代码:
package com.mec.about_bingfaThread;
/**
* * @author 橙橙橙。
*当从Runnable导出一个类时,它必须具有run()方法,但是这个方法并无特殊之处,它不会产生任何内在的线程能力。
*要实现线程行为,你必须显式地将一个任务附着到线程上。
*/
public class LiftOff implements Runnable{
protected int countDown = 10;
private static int taskCount = 0;
private final int id = taskCount++;
//id是用来区分任务的多个实例,它是final的,即要求一旦初始化,就不能被修改
public LiftOff() {
}
public String status() {
return "*" + id + "(" + (countDown > 0 ? countDown : "liftoff") + ").";
}
@Override
public void run() {
while (countDown-- > 0) {//在判断完成之后,才进行--操作
System.out.print(status() + " ");
Thread.yield();
}
}
public static void main(String[] args) {
LiftOff liftOff = new LiftOff();
liftOff.run();
}
}
来看一看运行结果:
*0(9). *0(8). *0(7). *0(6). *0(5). *0(4). *0(3). *0(2). *0(1). *0(liftoff).
看完上述代码,你会发现,它就是简单的实现了一个接口,并实现了接口中的方法,并没有线程的操作。事实上呢?你想的是对的,但是不全面,在main()方法中它是有线程的,是main主线程,除此之外其它操作于普通类相同。它主要是让我们来看看任务的id号,也就是将复杂的任务以id号进行显示,让我们明白在单个处理器中任务执行的过程。
yield()方法:调用此方法的线程会释放当前CPU的执行权,但是不会放弃资源锁。简单地说就是将CPU从一个线程转移给另一个线程。
-
Thread类是将Runnable对象转变为工作任务(线程)的具体实现
/**
* 以下程序会同时运行两个方法,main()和LiftOff.run()是程序中与其它线程“同时”执行的代码。
* @param args
* 任何线程都可以启动另一个线程
*/
public static void main(String[] args) {
LiftOff liftOff = new LiftOff();
Thread thread = new Thread(liftOff);
thread.start();
//start()方法用来启动一个新的线程,并且为该线程的执行必须的初始化操作,然后调用Runnable中的run()方法,
//以便在这个新线程中启动该任务;
System.out.println("Waiting for liftOff !");
}
这条代码仅是将main()函数的代码进行了变动,其他代码与上述代码一致。
查看运行结果:
Waiting for liftOff !
*0(9). *0(8). *0(7). *0(6). *0(5). *0(4). *0(3). *0(2). *0(1). *0(liftoff).
结果为什么是这样的?可能和它的内部配置有关系,请参考书中的一句话:实际上,你产生的是对LiftOff().run()的方法调用,并且这个方法还没有完成,但是因为LiftOff.run()是由不同的线程执行的,因此你仍旧可以执行main()线程中的其他操作。因此程序同时运行两个方法,main()和LiftOff()是程序中与其他线程"同时"执行的代码。
我的理解:这个程序中有两个线程,并且在Java中,线程的运行是抢占式的,start()方法中会调用run()方法,但是在调用run()方法之前,它还会为该线程执行必须的初始化操作,会消耗时间,等到时间片轮转到main()方法时,start()方法还没有执行完它应该执行的操作,所以main()线程执行了它的任务。
欢迎大家指点~