在此之前需要借助一个类,RunnableDemo,该类实现了Runnable接口.
public class RunnableDemo implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" RunnableDemo");
}
}
run()和start()
* start():是启动一个新线程,需要首先被启动,而且不能被重复.它会自动启动run方法
* run(): 和普通方法一样,线程启动后会自动调用run方法,可以重复调用.
*
* main MainThread
* main RunnableDemo
* subThread RunnableDemo
RunnableDemo runnableDemo = new RunnableDemo();
Thread subThread = new Thread( runnableDemo,"subThread" );
System.out.println(Thread.currentThread().getName()+" MainThread");
subThread.run(); //在主线程种调用 没有达到多线程的效果
subThread.start(); //重新开辟一个新线程,它会自己调用run方法.
//运行结果:main MainThread
// main RunnableDemo 这个是主线程中调用的run
// subThread RunnableDemo 这个是调用start方法,重新开辟的新线程
yield()
/**
* yield():让正在执行的线程从“运行状态”进入到“就绪状态”.
* 线程进入可运行状态(Runnable状态),该状态分为两个子状态:运行(Running)和就绪状态(Runnable).
* 运行状态是取得CPU周期并实际运行的,就绪状态是等待并争取使用CPU,这两个状态由运行调度器来控制.
* 线程可以使用yield()方法自动从运行状态让位到排队状态.
* 但是,并不能保证在当前线程调用yield()之后,
其它具有相同优先级的线程就一定能获得执行权;
也有可能是当前线程又进入到“运行状态”继续运行!
RunnableDemo runnableDemo = new RunnableDemo();
System.out.println(Thread.currentThread().getName()+" start");
Thread subThread = new Thread( runnableDemo,"subThread" );
subThread.start();
Thread.yield();
System.out.println(Thread.currentThread().getName()+" end");
//运行结果为main start
// main end
// subThread RunnableDemo
//可以看出 在subThread线程调用了start方法后,它为当前正在执行的线程,
// 当调用了yield后,让步于main线程了,等main线程执行完毕后,它又继续执行.*/
sleep()
sleep():让当前线程睡眠指定时间,在时间到达时自动回复线程的执行.它是Thread类的静态方法.参数填的是毫秒.
sleep方法不会释放线程锁.在线程重新被唤醒时,它会由“阻塞状态”变成“就绪状态”,从而等待CPU的调度执行
会抛出InterruptedException
join()
* join():等待线程,将当前子线程加入到父线程中,该子线程执行完毕后父线程再继续执行.*/
* 会抛出InterruptedException
* 使用方法:在父线程中进行调用.join的原理是用wait做的,所以其行为类似于wait.
RunnableDemo runnableDemo = new RunnableDemo();
System.out.println(Thread.currentThread().getName()+" start");
Thread subThread = new Thread( runnableDemo,"subThread" );
subThread.start(); //重新启动一个新线程
try {
subThread.join(); //当前子线程加入到主线程中.先执行子线程.
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" end");
//没有join的结果:main start 有join的结果:main start
// main end subThread RunnableDemo
// subThread RunnableDemo main end
//本来是主线程自己执行自己的,子线程自己执行自己的.相比之下主线程执行的快
// 加入join后,优先执行子线程再执行父线程.
//interrupt :终止处于“阻塞状态”的线程,当线程由于被调用了
sleep(),wait(),join()等方法而进入阻塞状态,
若此时调用线程的interrupt()将线程的中断标记设为true,由于处于阻塞状态,
终端标记会被清除同时产生一个InterruptedException异常.将InterruptedException放在适当的位置就能终止线程.
//isInterrupted() 判断中断是否发生,没有发生中断返回false,发生中断,返回true,并且把中断取消了.
//setDaemon: 设定守护线程 java中有两种线程 守护线程和用户线程 而守护线程也就是"后台线程".一般用来执行后台任务.
需要注意的是:java虚拟机在 "用户线程"都结束后会退出.
守护线程的生命周期依赖于用户线程,用户线程全部退出后,守护线程就会自动结束.
//isDaemon: 判断当前线程是否是守护线程
//setPriority() getPriority()
线程优先级 来知道JVM层面优先来执行哪个程序,但最终执行顺序需要操作系统来指定
java中的线程优先级范围是1-10 默认是5
"高优先级线程"会优先于"低优先级线程"执行
一个例子来带你更加深入了解join的使用
假如有三个线程,t1 t2 t3将线程按照t3 t2 t1顺序执行
线程1 2 3 同时开始.为了保证3 2 1 的顺序执行
只需要让线程2等待线程3执行完后自己再执行
只需要让线程1等待线程2和3执行完后自己再执行
所以在线程2的run方法种 用上线程3.join
在线程1的run方法种 用上线程2.join
RunnableDemo runnableDemo = new RunnableDemo();
final Thread thread3 = new Thread( runnableDemo,"thread3" );
final Thread thread2 = new Thread("thread2"){
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" start");
super.run();
try {
thread3.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" end");
}
};
Thread thread1 = new Thread( "thread1" ){
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" start");
super.run();
try {
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" end");
}
};
thread1.start();
thread2.start();
thread3.start();