Java多线程(二)线程调度

2022/3/3 22:14:57

本文主要是介绍Java多线程(二)线程调度,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

Java多线程(二)

1.线程的生命周期及状态转换

六种状态:

  • NEW(新建状态):创建一个线程后,该线程对象就处于新建状态,此时它不能运行,仅仅由JVM为其分配了内存,没有表现出任何线程的动态特征。
  • RUNNABLE(可运行状态):新建状态的线程调用start()方法就会进入可运行状态。在RUNNABLE状态又可细分成两种状态:READY(就绪状态)和RUNNING(运行状态),并且线程可以在二者间转换。
    • 就绪状态:调用start()方法后等待JVM调度。
    • 运行状态:线程对象获得JVM调度,若存在多个CPU,那么允许多个线程并行运行。
  • BLOCKED(阻塞状态):处于运行状态的线程可能会因为某些原因失去CPU执行权,暂时停止运行进入阻塞状态。此时JVM不会给线程分配CPU,直到线程重新进入就绪状态,才有机会转换到运行状态。一般以下两种情况会进入阻塞状态:
    • 线程A运行中,试图获取同步锁时,却被线程B获取,此时JVM把线程A存到对象的锁池中。
    • 线程运行过程中发出I/O请求时,此时该线程也会进入阻塞状态。
  • WAITING(等待状态):将运行状态的线程调用了无时间参数限制的方法后,如:wait()、join()等方法,就会将当前运行中的线程转换为等待状态。处于该状态时,必须等其他线程执行特定操作后,才有机会再次争夺CPU使用权,将等待状态的线程转换为运行状态。
  • TIMED_WAITING(定时等待状态):将运行状态的线程转换为定时等待状态与转换为等待状态操作类似,只是运行线程调用了有时间参数限制的方法。
  • TERMINATED(终止状态):线程的run()方法、call()方法正常执行完毕或线程抛出了一个未捕获的异常、错误,线程就进入终止状态。进入终止状态,线程不在拥有运行资格,也不能转换到其他状态,生命周期结束。

2.线程的调度

线程调度的两种模型:

  • 分时调度模型:让所有线程轮流获得CPU使用权。
  • 抢占式调度模型:让可运行池中所有就绪状态的线程抢占CPU的使用权,优先级高的线程获得CPU执行权的概率较大。

线程优先级

对线程进行调度,最直接的方法是设置线程优先级,用1~10之间的整数来表示,数字越大优先级越高。也可以使用Thread类的三个静态常量表示线程优先级。

static int MAX_PRIORITY		//最高优先级,相当于10
static int MIN_PRIORITY		//最低优先级,相当于1
static int NORM_PRIORIY		//普通优先级,相当于5

程序运行期间,就绪状态的每个线程都有优先级,如main()具有普通优先级。线程优先级不是固定不变的,可以通过Thread类的setPriority(int newPriority)方法进行设置。

举例:

public class Page364 {
    public static void main(String[] args) {
        Thread thread1=new Thread(()->{
            for(int i=0;i<10;i++){
                System.out.println(Thread.currentThread().getName()+"正在输出i:"+i);
            }
        },"优先级较低的线程");
        Thread thread2=new Thread(()->{
            for(int j=0;j<10;j++){
                System.out.println(Thread.currentThread().getName()+"正在输出j:"+j);
            }
        },"优先级较高的线程");
        thread1.setPriority(Thread.MIN_PRIORITY);
        thread2.setPriority(10);
        thread1.start();
        thread2.start();
    }
}

3.线程休眠

使用静态方法sleep(long millis)方法使线程暂停一段时间,这样其他线程就可以得到执行机会。但该方法会抛出InterruptedException异常,因此调用该方法时应捕获异常或声明抛出异常。

举例:

public class Page365 {
    public static void main(String[] args) {
        Thread thread1=new Thread(()->{
            for(int i=0;i<10;i++){
                System.out.println(Thread.currentThread().getName()+"正在输出i:"+i);
                if(i==2){
                    try{
                        Thread.sleep(500);
                    }catch(InterruptedException e){
                        e.printStackTrace();
                    }
                }
            }
        });
        Thread thread2=new Thread(()->{
            for(int j=0;j<10;j++){
                System.out.println(Thread.currentThread().getName()+"正在输出j:"+j);
            }
        });
        thread1.start();
        thread2.start();
    }
}

4.线程让步

线程让步可以通过yield()方法来实现,与sleep()有点类似,都可以让正在运行的线程暂停,但yield()不会阻塞该线程,它只是将线程转换成就绪状态,让系统的调度器重新调度一次,,使用yield()后,与当前线程优先级相同或更改的线程可以获得执行机会。
举例:

class YieldThread extends Thread{
    public YieldThread(String name){
        super(name);
    }
    public void run(){
        for(int i=0;i<5;i++){
            System.out.println(Thread.currentThread().getName()+"---"+i);
            if(i==2){
                System.out.println("线程让步");
                Thread.yield();
            }
        }
    }
}

public class Page367 {
    public static void main(String[] args) {
        Thread thread1=new YieldThread("thread1");
        Thread thread2=new YieldThread("thread2");
        thread1.start();
        thread2.start();
    }
}

5.线程插队

Thread类中提供了join()方法,在某个线程中调用其他线程的join()方法时,调用的线程将被堵塞,直到被join()方法加入的线程执行完成之后它才会继续运行。

举例:

class EmergencyThread implements Runnable{
    public void run(){
        for(int i=1;i<6;i++){
            System.out.println(Thread.currentThread().getName()+"输入:"+i);
        }
    }
}

public class Page368 {
    public static void main(String[] args) throws InterruptedException{
        Thread thread1=new Thread(new EmergencyThread(),"thread1");
        thread1.start();
        for(int i=1;i<6;i++){
            System.out.println(Thread.currentThread().getName()+"输入:"+i);
            if(i==2){
                thread1.join();
            }
        }
    }
}


这篇关于Java多线程(二)线程调度的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程