多线程:程序同一时刻内执行多个任务;在每一个程序中的main方法就是一个线程,称之为主线程。在主线程内可以启动多个子线程。
定义线程的两种方法
1)通过继承Thread类,重写run()方法。
2)实现Runnable接口内的抽象方法run()。
public class XianCheng extends Thread {
@Override
public void run() {
System.out.println("通过继承Thread定义线程,在run方法内定义该线程执行语句");
}
}
public class XianCheng2 implements Runnable {
public void run() {
System.out.println("通过实现Runnable接口实现线程");
}
}
public class XianChengTest {
public static void main(String[] args) {
System.out.println("启动主线程 ");
// 通过继承Thread定义线程方式创建线程对象
XianCheng xc = new XianCheng();
// 通过实现Runnable接口实现线程方式创建线程对象
XianCheng2 xc2 = new XianCheng2();
Thread t = new Thread(xc2);
XianCheng2 xc3 = new XianCheng2();
Thread t2 = new Thread(xc3);
// 启动线程:需要调用线程对象的start()方法; 注意:并非是直接调用run(),如果直接调用run(),只是对象方法的普通调用。
xc.start(); // 线程1,与main()方法并列执行的
t.start(); // 线程2,与main()方法并列执行的
t2.start(); // 线程3,与main()方法并列执行的, 同时运行多线程,首先执行哪个线程是不确定性的。
}
}
线程的生命周期
1)新建状态:一个线程对象被创建后,线程就处于新建状态。
2)准备状态:线程对象被调用start()后进入准备状态。可以同时存在多个线程处在准备状态,对于哪个线程进入运行状态是不确定性的。线程进入准备状态后不能再进入新建状态。在处于等待/阻塞状态的线程被解除等待和阻塞后不能执行进入运行状态,而是进入准备状态。再由系统自动选择哪个线程进入运行状态。
3)运行状态:处于准备状态的线程一旦被系统选中,使线程获得了CPU时间,则该线程就会进入运行状态。运行状态中将执行线程的run()方法。进入运行状态后的线程不一定是一下子执行结束的。随时都有可能被调度程序调度回准备状态,或者进入等待/阻塞状态。单核CPU,同一时刻只有一个线程处于运行状态;多核CPU中同一时刻可以存在多个线程运行状态。
4)等待/阻塞状态:处于等待/阻塞状态的线程被解除后,会进入准备状态,等待系统的调度。
5)死亡状态:在线程的run()方法执行结束后,或者程序发生异常终止执行后,线程就会进入死亡状态。处于死亡状态的线程不能再使用start()方法启动线程。可以被作为普通的类来使用。
线程的调度
原因:线程的执行,通过系统自动调度的,线程的执行顺序是不确定性的。定义一些调度方法控制系统的调度。这些方法也是不一定能完全控制系统调度的,只是给系统调度的一些指引。
调度方法
1)睡眠方法:当线程处于运行状态时,调用sleep("线程睡眠的毫秒数")睡眠方法将使线程进入等待/阻塞状态,从而使程序停止运行。
// 睡眠方法的两种语法格式
public static void sleep(long millis) throws InterruptedException;
public static void sleep(long millis, int nanos) throws InterruptedException;
2)设置优先级:大部分系统中对线程的调度都是采用优先级的方式。优先级采用从1到10来表示,数值越大优先级越高,优先级越高的线程就会占用更多的CPU资源和被执行效率。java中线程默认优先级为5。Thread类中定义了优先级的常量;MAX_PRIORITY,MIN_PRIORITY, NORM_PRIORITY。
// 调用优先级语法
public final void setPriority(int i){}
3)让步方法:包含两种
第一种:yield让步方法,即让线程让出当前CPU,但是将CPU让给哪个线程是不确定的,由系统自动调度。使用yield让步方法会将线程从运行状态进入准备状态。让步方法并非一定成功的,进入准备状态的此线程也有可能被系统重新调度。
语法:public static void yield(){};
第二种:join让步方法,即将当前线程的CPU让给指定的线程。
// join的三种语法
public final void join() throws InterruptedException;
public final void join(long millis) throws InterruptedException;
public final void join(long millis, int nanos) throws InterruptedException;