本文主要介绍线程的相关调度方法
1.sleep()方法
让当前线程暂停执⾏,从运⾏状态进⼊阻塞状态,将 CPU 资源让给其他线程的调度⽅式,通过 sleep()来实现。
sleep(long millis),调⽤时需要传⼊休眠时间,单位为豪秒。
自定义一个线程类
public class MyThread extends Thread {
@Override
public void run() {
for (int i=0;i<10;i++){
if (i == 5){
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i + "------MyThread1");
}
}
}
test类
public class MyTest {
public static void main(String[] args) {
MyThread thread1 = new MyThread();
thread1.setName("线程1");
thread1.start();
}
}
控制台上可发现运行到i = 4的时候,停了一秒钟。
2.线程合并-join方法
合并是指将指定的某个线程加⼊到当前线程中,合并为⼀个线程,由两个线程交替执⾏变成⼀个线程中的两个子线程顺序执⾏。
通过调⽤ join ⽅法来实现合并,具体如何合并?
线程甲和线程⼄,线程甲执⾏到某个时间点的时候调⽤线程⼄的 join⽅法,则表示从当前时间点开始CPU 资源被线程⼄独占,线程甲进⼊阻塞状态,直到线程⼄执⾏完毕,线程甲进⼊就绪状态,等待获取CPU 资源进⼊运⾏状态。
join ⽅法重载,join() 表示⼄线程执⾏完毕之后才能执⾏其他线程,join(long millis) 表示⼄线程执⾏millis 毫秒之后,⽆论是否执⾏完毕,其他线程都可以和它争夺 CPU 资源。
代码演示:
自定义runable实现类
public class MyRunable1 implements Runnable {
@Override
public void run() {
for (int i = 0;i < 200; i++){
System.out.println("----MyRunable");
}
}
}
测试类
public class MyTest {
public static void main(String[] args) {
/*
* sleep()
* */
/*MyThread thread1 = new MyThread();
thread1.setName("线程1");
thread1.start();*/
/*
* join()-线程合并
* */
MyRunable1 runable1 = new MyRunable1();
Thread thread1 = new Thread(runable1);
thread1.start();
for (int i = 0;i < 100; i++){
if (i == 20){
try {
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i + "我是主线程");
}
}
}
查看结果可发现,到19的时候主线程就停了,让thread1执行完才开始执行的。
join(1000)的效果就是,thread1执行了一秒后,主线程和thread1又开始互相抢占资源,交替执行。
3. yield()-线程礼让
线程礼让是指在某个特定的时间点,让线程暂停抢占 CPU 资源的⾏为,运⾏状态/就绪状态—》阻塞状态,将 CPU 资源让给其他线程来使⽤。
假如线程甲和线程⼄在交替执⾏,某个时间点线程甲做出了礼让,所以在这个时间节点线程⼄拥有了CPU 资源,执⾏业务逻辑,但不代表线程甲⼀直暂停执⾏。
线程甲只是在特定的时间节点礼让,过了时间节点,线程甲再次进⼊就绪状态,和线程⼄争夺 CPU 资源。
代码演示:
thread1
public class MyThread1 extends Thread {
@Override
public void run() {
for (int i=0;i<10;i++){
if (i == 2){
yield();
}
System.out.println(Thread.currentThread().getName()+i+"=====Thread1");
}
}
}
thread2
public class MyThread2 extends Thread {
@Override
public void run() {
for (int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+i+"Thread2======");
}
}
}
test类
public class MyTest {
public static void main(String[] args) {
/*
* sleep()
* */
/*MyThread thread1 = new MyThread();
thread1.setName("线程1");
thread1.start();*/
/*
* join()-线程合并
* */
/*MyRunable1 runable1 = new MyRunable1();
Thread thread1 = new Thread(runable1);
thread1.start();
for (int i = 0;i < 100; i++){
if (i == 20){
try {
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i + "我是主线程");
}*/
/*
* yield()-线程合并
* */
MyThread1 thread1 = new MyThread1();
thread1.setName("线程甲");
MyThread2 thread2 = new MyThread2();
thread2.setName("线程乙");
thread1.start();
thread2.start();
}
}
效果可能有些不佳,知道意思就行。
4.线程中断
有很多种情况会造成线程停⽌运⾏:
- 线程执⾏完毕⾃动停⽌
- 线程执⾏过程中遇到错误抛出异常并停⽌
- 线程执⾏过程中根据需求⼿动停⽌
Java 中实现线程中断有如下⼏个常⽤⽅法:
1.public void stop()
2.public void interrupt()
3.public boolean isInterrupted()
stop ⽅法在新版本的 JDK 已经不推荐使⽤,重点关注后两个⽅法。
interrupt 是⼀个实例⽅法,当⼀个线程对象调⽤该⽅法时,表示中断当前线程对象。
每个线程对象都是通过⼀个标志位来判断当前是否为中断状态。
isInterrupted 就是⽤来获取当前线程对象的标志位:true 表示清除了标志位,当前线程已经中断;false 表示没有清除标志位,当前对象没有中断。
当⼀个线程对象处于不同的状态时,中断机制也是不同的。
1.创建状态:实例化线程对象,不启动。
public class Test {
public static void main(String[] args) {
Thread thread = new Thread();
System.out.println(thread.getState());
thread.interrupt();
System.out.println(thread.isInterrupted());
}
}
执行结果
NEW 表示当前线程对象为创建状态,false 表示当前线程并未中断,因为当前线程没有启动,不存在中断,不需要清除标志位。
public class Test2 {
public static void main(String[] args) {
// MyRunnable runnable = new MyRunnable();
// Thread thread = new Thread(runnable);
// thread.start();
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
for(int i = 0; i < 10;i++) {
System.out.println(i+"---main");
}
}
});
thread.start();
System.out.println(thread.getState());
thread.interrupt();
System.out.println(thread.isInterrupted());
System.out.println(thread.getState());
}
}