Thread的start和run
1) start:
用start方法来启动
线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到spu时间片,就开始执行run()方法,这里方法run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止。
2) run:
run()方法只是类的一个普通方法而已,如果直接调用Run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码,这样就没有达到写线程的目的。
总结:调用start方法方可启动线程,而run方法只是
thread的一个普通方法调用,还是在主线程里执行。
class="java" name="code">public class SMSSample implements Runnable {
public static void main(String[] args) {
new SMSSample().multiThreadSendMsg(); // 调用多线程进行测试
}
}
// 多线程发送短信测试
public void multiThreadSendMsg() {
int threadCount =150; //线程数压力测试变量
Runnable target = new SMSSample();
long start = System.currentTimeMillis();
for (int i = 0; i < threadCount; i++) {
Thread thread = new Thread(target);
thread.setName("Thead-Call-SMSSample-"+i);
System.out.println("---------线程的名字是:" + thread.getName());
System.out.println("---------线程的ID是:" + thread.getId());
thread.start();
}
}
}
@Override
public void run() {
线程体context;
try {
while(canStart){ }
}catch (Exception e) {
e.p...
}
}
— void notifyAll():唤醒在此对象上等待的所有线程
— void wait():使线程陷入一直等待的状态,除非被唤醒。
— void wait(long timeout):使线程等待timeout指定的毫秒数。当等待时间已满,或者被唤醒,线程将重新被线程调度器调度。如果timeout为0,则等同于wait()。
— Thread.sleep():当处于运行状态的线程调用Thread类的sleep()方法之后,线程将在方法参数指定的时间段之内进入休眠状态,即在不释放任何运行资源的情况下停止运行。当休眠时间结束,或者捕获并响应由于Thread.interrupt()方法引起的 InterruptedException
异常之后,线程回到运行状态。
---------------------------------------------------
线程的状态
可以将线程分为创建、就绪、运行、休眠、挂起和死亡等类型。在不同类型的线程状态下,线程的特征如下所示。
— 创建状态:当利用new
关键字创建线程对象实例后,它仅仅作为一个对象实例存在,
JVM没有为其分配CPU时间片等运行资源。
— 就绪状态:对处于创建状态的线程调用Thread类的start()方法将线程的状态转换为就绪状态。这时,线程已经得到除CPU时间片之外的其他系统资源,只等JVM的线程调度器按照线程的优先级对该线程进行调度,从而使该线程拥有能够获得CPU时间片的机会。
— 运行状态:JVM的线程调度器选中处于就绪状态的线程,使其获得CPU时间片。
— 休眠状态:
在线程运行过程中可以调用Thread类的sleep()方法,并在方法参数中指定线程的休眠时间将线程状态转换为休眠状态。这时,该线程在指定的休眠时间内,在不释放占用资源的情况下停止运行。时间到达后,线程重新进入运行状态。处于休眠状态的线程,可能遇上 java.lang.InterruptedException异常,从而被迫停止休眠。
— 挂起状态:可以通过调用Thread类的suspend()方法将线程的状态转换为挂起状态。这时,线程将释放占用的所有资源,由JVM调度转入临时存储空间,直至应用程序调用Thread类的resume()方法恢复线程运行。
— 死亡状态:当线程体运行结束或者调用线程对象的Thread类的stop()方法后线程将终止运行,由JVM收回线程占用的资源。
— Thread.yield():当处于运行状态的线程调用Thread类的yield()方法之后,线程所拥有的CPU时间片被剥夺,重新回到就绪状态,等候JVM线程调度器的调度。
— Thread.sleep():当处于运行状态的线程调用Thread类的sleep()方法之后,线程将在方法参数指定的时间段之内进入休眠状态,即在不释放任何运行资源的情况下停止运行。当休眠时间结束,或者捕获并响应由于Thread.interrupt()方法引起的 InterruptedException异常之后,线程回到运行状态。
— Object.wait():当处于运行状态的线程调用Object类的wait()方法之后,线程将方法参数指定的时间段之内、在保留运行状态的情况下回到就绪状态。Object类的wait()方法支持无参调用,表示一直停止运行,等待被Object.notify()方法唤醒。
— Object.notify():如果线程不处于就绪(等待)状态,则调用Object类的notify()方法不起任何作用;否则线程将重新获得竞争CPU时间片的资格,从等待之前的状态点开始运行。
— Thread.stop():终止线程,线程将释放占用的全部资源。该方法已被禁用。
— Thread.join():结束线程,并等待方法参数指定的时间段。在等待期间,如果线程已经结束,则立刻返回。Thread.join()方法是推荐的结束线程的方法。
— Thread.suspend()、Thread.resume()、Thread.stop()方法已被禁用,因此线程的状态实际上只有5种:创建、就绪、运行、休眠和死亡。
线程的等待和唤醒
使线程中断运行,返回就绪状态的手段是调用java.lang.Object对象的wait()方法;唤醒处于等待状态的线程的手段是调用java.lang.Object对象的notify()方法。对wait()和notify()方法说明如下。
— void wait():使线程陷入一直等待的状态,除非被唤醒。
— void wait(long timeout):使线程等待timeout指定的毫秒数。当等待时间已满,或者被唤醒,线程将重新被线程调度器调度。如果timeout为0,则等同于wait()。
— void wait(long timeout,int nanos):使线程等待timeout指定的毫秒数+nanos指定的微秒数。当等待时间已满,或者被唤醒,线程将重新被线程调度器调度。如果timeout和nanos均为0,则等同于wait()。
— void notify():唤醒在此对象上等待的一个线程,如果在此对象上有多个线程同时在等待,则任意唤醒其中一个。
— void notifyAll():唤醒在此对象上等待的所有线程
线程的休眠和中断
线程的休眠状态和就绪(包括等待)状态的不同之处在于,处于休眠状态的线程并不释放运行资源,在休眠结束之后,不用等待被JVM线程调度器再度选中,而可以直接进入运行状态。结束休眠状态有两种途径:(1)休眠时间到达后,线程重新进入运行状态;(2)处于休眠状态的线程遇上java.lang.InterruptedException异常,从而被迫停止休眠。
使当前线程进入休眠状态的手段是调用Thread类的sleep()方法,该方法是
静态方法,这意味着不用指定Thread对象便可以直接使用。打断某线程的休眠状态的手段是调用该线程对象的interrupt()方法。对 sleep()和interrupt()方法说明如下。
— void sleep(long timeout):使当前线程休眠timeout指定的毫秒数。在休眠过程中,如果遇上中断,则抛出InterruptedException异常。
— void sleep(long timeout,int nanos):使当前线程休眠timeout指定的毫秒数+nanos指定的微秒数。在休眠过程中,如果遇上中断,则抛出InterruptedException异常。
— void interrupt():中断线程的休眠状态。
线程的终止
对于终止运行中的线程,Thread类原本提供了一个停止线程的方法:stop(),但是实践证明该方法具有固有的不
安全性,因此已被弃用。
结合目前我们已经掌握的技能,已经能够完美地终止线程,那便是利用线程的休眠和中断机制,在子线程中有意地为调度线程(比如创建线程的主线程)安排中断机会。
利用线程的休眠和中断机制,可以不留遗患地完美结束线程,是终止线程的推荐做法。例程虽然很简单,但是对于更复杂的场景,也可以遵照这个模型来设计线程的终止机制。
在和终止线程有关的方法中,Thread类还提供了一系列join()方法来等待线程结束。请注意,join()方法并不能终止某线程,而是提供了一个阻塞当前线程、等待某线程终止的途径。对join()方法说明如下。
— void join():一直阻塞当前线程,等待线程结束。在等待过程中,如果遇上中断请求,则抛出InterruptedException异常。
— void join(long timeout):在timeout指定的毫秒时间内阻塞当前线程,等待线程结束。在等待过程中,如果遇上中断请求,则抛出InterruptedException异常。
— void join(long timeout, int nanos):在timeout指定的毫秒+nanos指定的微秒时间内阻塞当前线程,等待线程结束。在等待过程中,如果遇上中断请求,则抛出InterruptedException异常。