java线程控制
1、线程睡眠 sleep()
2、线程优先级 setPriority()
3、线程让步 Thread.yield()
4、守护线程 setDaemon(true)
5、线程合并 join()
一、线程睡眠 sleep() Thread.sleep(long millis) 单位:毫秒(ms)
如果需要让当前正在执行的线程暂停一段时,并进入阻塞状态,则可以通过调用Thread类的静态sleep()方法来实现。线程调用sleep()方法进入阻塞状态后,在其睡眠时间段内,该线程不会获得执行的机会,即使系统中没有其他可执行的线程,处于sleep()中的线程也不会执行,因此sleep()方法常用来暂停程序的执行。
代码示例:
public class Demo01 {
public static void main(String[] args) {
Thread thread = new Thread(new Thread1());
thread.start();
}
}
class Thread1 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println(Thread.currentThread().getName() + "---->" + i);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
二、线程优先级 setPriority()
Thread类有三个静态常量,用于线程优先级设置,当然你也设置其他整数
设置线程的优先级:线程级别越高CPU为它服务的概率越大,不设置的话默认是NORM_PRIORITY(5)。
示例代码
/**
* 线程优先级
* 注意:先设置优先级在启动线程
*/
public class Demo02 {
public static void main(String[] args) {
Thread2 t1 = new Thread2("线程一");
Thread2 t2 = new Thread2("线程二");
t2.setPriority(Thread.MAX_PRIORITY); // 设置t2线程的优先级为10
t1.setPriority(1); // 设置t2线程的优先级为1
t1.start(); // 启动t1线程
t2.start(); // 启动t2线程
}
}
class Thread2 extends Thread {
public Thread2(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
System.out.println(Thread.currentThread().getName() + "--------->" + i);
}
}
}
运行结果:程序中设置了t2线程的优先级高于t1所以每次运行总是t2线程先结束。
三、线程让步 Thread.yield()
yield()方法也是Threard类提供的一个静态方法,它也可以让当前正在执行的线程暂停,但它不会阻塞该线程,它只是将该线程转入就绪状态。yield()只是让当前线程暂停一下,同时也会争夺下一次的CPU资源。有可能会某线程刚调用yield()方法让出CPU资源,又获得的CPU资源的情况。
实际上,当某个线程调用了yield()方法暂停之后,只有优先级与当前线程相同,或者优先级比当前线程更高的处于就绪状态的线程才会获得执行的机会。
示例代码:
/**
* 线程让步
*/
public class Demo03 {
public static void main(String[] args) {
Thread3 t1 = new Thread3("线程一");
Thread3 t2 = new Thread3("线程二");
t1.start();
t2.start();
}
}
class Thread3 extends Thread {
public Thread3(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
System.out.println(Thread.currentThread().getName() + "--------->" + i);
Thread.yield();
}
}
}
运行结果:t1、t2两个线程互相让步同时又互相争夺CPU资源。
四、守护线程 setDaemon(true)
有一种线程,它是在后台运行的,它的任务是为其他的线程提供服务,这种线程被称为后台线程(Daemon Thread),又称为守护线程或精灵线程。JVM的垃圾回收线程就是典型的后台线程。后台线程有个特征:如果所有的前台线程都死亡,后台线程会自动死亡。
代码示例:
/**
* 守护线程
*/
public class Demo04 {
public static void main(String[] args) {
Thread4 t = new Thread4();
t.setDaemon(true);
t.start();
/**
* main线程业务逻辑
*/
for (int i = 0; i < 10000; i++) {
System.out.println(Thread.currentThread().getName() + "***********>" + i);
}
}
}
class Thread4 extends Thread {
public Thread4() {
super("后台线程");
}
@Override
public void run() {
for (int i = 0; i < 100000; i++) {
System.out.println(this.getName() + "----------->" + i);
}
}
}
运行结果:main线程的执行时间明显会比t线程执行的时间要短,设置了t线程为后台线程,当main线程结束后t线程也会结束,即t线程不会循环到99999。
五、线程合并 join()
Thread提供了让一个线程等待另一个线程完成的方法join()方法。当在某个程序执行流中调用其他线程的join()方法时,调用线程将被阻塞,直到被join()方法加入的join线程执行完为止。常用于有先后顺序的线程之间。如(将大象装入冰箱:第一步打开冰箱门 à 第二步将大象装入冰箱à第三步关闭冰箱门)
示例代码:用main线程作为调用线程
/**
* 线程join
*/
public class Demo05 {
public static void main(String[] args) throws Exception {
T1 t1 = new T1();
T2 t2 = new T2();
T3 t3 = new T3();
for (int i = 1; i < 1000; i++) {
if (i == 10) {
t1.start();
t1.join(); // main线程在此join了t1线程 ,main要等t1执行完后 main继续
}
if (i == 100) {
t2.start();
t2.join();// main线程在此join了t2线程 ,main要等t2执行完后 main继续
}
if (i == 500) {
t3.start();
t3.join(); // main线程在此join了t3线程 ,main要等t3执行完后 main继续
}
System.out.println(Thread.currentThread().getName() + "~~~~~~~~" + i);
}
}
static class T1 extends Thread {
public T1() {
super("打开冰箱门");
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println(this.getName() + "--->" + i);
}
}
}
static class T2 extends Thread {
public T2() {
super("关闭冰箱门");
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println(this.getName() + "--->" + i);
}
}
}
static class T3 extends Thread {
public T3() {
super("将大象装入冰箱");
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println(this.getName() + "--->" + i);
}
}
}
}
运行结果:1-9执行main线程,之后t1线程加入main线程等到t1线程结束才向下执行,10-99执行main线程,之后t2线程加入main线程等到t2线程结束才向下执行,100-499执行main线程,之后t3线程加入main线程等到t3线程结束才向下执行,在向下执行main线程。