线程控制
我们已经知道了线程的调度,接下来我们就可以使用如下方法对象线程进行控制。
1.线程休眠
public static void sleep(long millis)
:让当前线程处于暂停状态,millis
参数毫秒值,即暂停时间。
代码演示如下:
1.MyThread.java:
public class MyThread extends Thread {
public MyThread() {
}
public MyThread(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
try {
// 线程休眠 1000ms 即 1s
sleep(1000);
System.out.println("我是---->" + getName() + ":" + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
2.Test.java:
public class Test {
public static void main(String[] args) {
MyThread t1 = new MyThread("张飞");
MyThread t2 = new MyThread("关羽");
t1.start();
t2.start();
}
}
线程加入(线程强制执行)
public final void join()
:后面其他线程等待,当前线程执行完,后面其他线程再开始执行。
调用必须是在当前线程start以后,其他线程start之前。
代码演示如下:
1.MyThread.java:
public class MyThread extends Thread {
public MyThread() {
}
public MyThread(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
try {
// 线程休眠 100ms
sleep(100);
System.out.println("我是---->" + getName() + ":" + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
2.Test.java:
public class Test {
public static void main(String[] args) throws InterruptedException {
MyThread t0 = new MyThread("刘备");
MyThread t1 = new MyThread("张飞");
MyThread t2 = new MyThread("关羽");
t0.start();
// 线程加入 线程强制执行
// 运行结果 刘备先买完,然后张飞关羽再多线程买
t0.join();
t1.start();
t2.start();
//如果这样
/*
t1.start();
t0.start();
// 线程加入 线程强制执行
// 运行结果 刘备张飞多线程买,都买完之后,关羽再买
t0.join();
t2.start();
*/
}
}
3.线程礼让
public static void yield()
:当前执行的线程,执行完毕后会礼让后面的线程。也就是说最好的情况就是每个线程都交替执行,没有连续多次执行同一个线程的情况发生。
但是由于线程执行具有随机性,所以该方法并不能保证完全的交替执行,所以说效果并不好,用处较少。
演示代码如下:
1.MyThread.java:
public class MyThread extends Thread {
public MyThread() {
}
public MyThread(String name) {
super(name);
}
@Override
public void run() {
// 线程礼让
Thread.yield();
for (int i = 0; i < 20; i++) {
try {
// 线程休眠 100ms
sleep(100);
System.out.println("我是---->" + getName() + ":" + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
2.Test.java:
public class Test {
public static void main(String[] args) throws InterruptedException {
MyThread t1 = new MyThread("张飞");
MyThread t2 = new MyThread("关羽");
t1.start();
t2.start();
}
}
4.后台线程(守护线程)
public final void setDaemon(boolean on)
:被守护线程如果执行结束,则守护线程直接终止,不继续执行任何一行代码。
注意:守护线程要在声明后,和start()
前声明。否则报错!
演示代码如下:
刘关张三兄弟,一起上阵杀敌。
目的:一旦刘备(主公)死了,关羽张飞就不再杀敌直接被俘虏了。
1.MyThread.java:
public class MyThread extends Thread {
public MyThread() {
}
public MyThread(String name) {
super(name);
}
@Override
public void run() {
System.out.println(getName() + "--->已经到达战场!");
// 线程礼让
Thread.yield();
for (int i = 0; i < 20; i++) {
try {
// 线程休眠 100ms
sleep(100);
System.out.println(getName() + "开始对抗第 " + i + " 个敌人");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(getName() + "--->战死了!!!!");
}
}
2.Test.java:
public class Test {
public static void main(String[] args) throws InterruptedException {
MyThread t1 = new MyThread("张飞");
MyThread t2 = new MyThread("关羽");
// 设置后台线程 守护线程
t1.setDaemon(true);
t2.setDaemon(true);
t1.start();
t2.start();
System.out.println("刘备----->到达战场!!!!");
for (int i = 0; i < 10; i++) {
// 为了明显让主线程也休眠
Thread.sleep(100);
System.out.println("刘备开始对抗第 " + i + " 个敌人");
}
System.out.println("刘备战死了!!!!");
}
}
5.中断线程
例子:刘关张三兄弟都困了,刘备先挺不住睡觉了,关羽张飞看到就也睡觉了,但是刘备先醒了,看到他们两个在睡觉,就把他们两个叫醒了。
public final void stop()
:不推荐使用,此方法太血腥。直接中断线程,后面代码不执行了。
例子中,就是刘备醒了后看到两兄弟在睡觉,很生气,叫人把他们弄死了。两兄弟再也睡不醒了。
public void interrupt()
:不推荐使用,此方法太暴力,直接给当前线程抛出了一个异常。
Interrupt()
方法会向子线程抛出一个InterruptedException
异常,异常结束了子线程的休眠。
推荐使用的方法:
像停止一个高速旋转的轮子一样,慢慢停止旋转。
代码:一般子线程里面都是长循环或耗时操作,只要把长循环或耗时操作的状态改为不再循环,则慢慢停止。
推荐使用:布尔值,控制循环停止,温和终止方式。
演示代码如下:
1.MyThread.java:
public class MyThread extends Thread {
public MyThread() {
}
public MyThread(String name) {
super(name);
}
@Override
public void run() {
System.out.println(getName() + "--->开始睡觉!!!");
try {
for (int i = 0; i < 10 && Flag.FLAG; i++) {
// 线程休眠 1000ms
sleep(1000);
System.out.println(getName() + "--->正在睡觉--" + i);
}
} catch (InterruptedException e) {
System.out.println(getName() + "--->被一棒子打醒!");
}
System.out.println(getName() + "--->睡醒了!!!");
}
}
2.Flag.java:
public class Flag {
//仅仅用来判断循环是否继续
public static boolean FLAG = true;
}
3.Test.java:
public class Test {
public static void main(String[] args) throws InterruptedException {
MyThread t1 = new MyThread("张飞");
MyThread t2 = new MyThread("关羽");
t1.start();
t2.start();
System.out.println("刘备----->开始睡觉!!!!");
// 为了明显让主线程也休眠
Thread.sleep(3000);
System.out.println("刘备睡醒了!!!!");
// 使用boolean值控制循环停止,温和
// 刘备睡醒后二人也能再睡短短的一会儿,然后被温柔的叫醒
Flag.FLAG = false;
// 太暴力,一棒子打醒了二人
// t1.interrupt();
// t2.interrupt();
// 太血腥,直接弄死了二人,再也睡不醒了
// t1.stop();
// t2.stop();
}
}