1.start()和run()
执行的线程,一定要调用它的start()方法。不能调用run()方法。
如果直接调用线程对象的run()方法,程序也会执行,但那样是在当前线程中执行,不会启动新的线程。
start()方法的本质是从CPU中申请一个新的线程空间来执行 run()方法中的代码。
run()方法的本质是只是线程的接口回调方法。
一个线程对象只能运行成功一次start()方法,即
已经调用start()方法的对象不能再次调用start()方法,否则会抛异常。
2.sleep()
sleep()是静态方法,使正在运行的线程进入TIMED_WAITING状态,但不释放对象锁。
睡眠时间到了,会进入就绪状态。
给其他线程执行机会。
sleep()方法声明抛出了InterruptedException
在sleep 时间间隔期满后,线程不一定立即恢复执行,
即:
Thread.sleep(1000)使得线程睡眠1秒,可能结果会大于1秒
除非:
a.醒来的线程具有更高的优先级。
b.正在运行的线程因为其它原因而阻塞。
所以:
程序员只能最大限度的影响线程执行的次序,而不能做到精准控制。
sleep()方法是静态方法,只对正在运行状态的线程对象有效。如:
public class TestThread {
public static void main(String[] args) throws InterruptedException {
System.out.println(Thread.currentThread().getName());
Thread threadNew=new Thread();
threadNew.start();
//这里是主线程sleep,而不是threadNew线程
threadNew.sleep(1000);
System.out.println(Thread.currentThread().getName());
Thread.sleep(10);
for(int i=0;i<100;i++){
System.out.println("main"+i);
}
}
}
3.yield()
yield()是静态方法,使正在运行的线程进入就绪状态,不释放对象锁。
yield()方法声明没有抛出异常。
yield()方法是让系统的线程调度器重新调度当前线程。让相同优先级的线程轮流执行,但并不保证一定会轮流执行。
可能:
当某个线程调用yield()方法之后,线程调度器又将其调度出来重新进入到运行状态执行。
比较:
3.1 yield()方法和sleep()方法,都是Thread类的静态方法。
3.2 yield()方法让线程进入就绪状态。sleep()方法让线程进入阻塞状态,睡眠时间到了,再进入就绪状态。
3.3 sleep()、wait()、join() 都抛出了InterruptedException,yield()没有。
3.4 通常不用yield()方法,因为移植性不好。而用sleep()方法。
4.join()
将几个并行线程的线程合并为一个单线程执行,
应用场景是当一个线程必须等待另一个线程执行完毕才能执行时,
它不是静态方法。
它有3个重载的方法:
void join()
当前线程等该加入该线程后面,等待该线程终止。
void join(long millis)
当前线程等待该线程终止的时间最长为 millis 毫秒。 如果在millis时间内,该线程没有执行完,那么当前线程进入就绪状态,重新等待cpu调度
void join(long millis,int nanos)
等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。如果在millis时间内,该线程没有执行完,那么当前线程进入就绪状态,重新等待cpu调度
public class Test1 {
public static void main(String[] args) throws InterruptedException {
MyThread thread=new MyThread();
thread.start();
thread.join(1);//将主线程加入到子线程后面,不过如果子线程在1毫秒时间内没执行完,则主线程便不再等待它执行完,进入就绪状态,等待cpu调度
for(int i=0;i<30;i++){
System.out.println(Thread.currentThread().getName() + "线程第" + i + "次执行!");
}
}
}
class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println(this.getName() + "线程第" + i + "次执行!");
}
}
}
在这个例子中,在主线程中调用thread.join(); 就是将主线程加入到thread子线程后面等待执行。不过有时间限制,为1毫秒。