首页 > 编程语言 > 详细

多线程学习---让出执行权、线程中断

时间:2021-04-11 21:16:42      阅读:8      评论:0      收藏:0      [点我收藏+]

yield()让出CPU执行权 

 Thread类中有一个静态的yield方法,当一个线程调用yield方法时候,当前执行线程会让出自己的CPU使用权,然后处于就绪状态,线程调度器会从线程就绪队列里面获取一个线程优先级最高的线程,当然也有可能会调度到刚刚让出CPU的那个线程来获取CPU执行权。

public class YieldTest implements Runnable {

    YieldTest(){
        //创建并启动线程
        Thread thread=new Thread(this);
        thread.start();
    }
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"执行开始");
        for(int i=0;i<5;i++){
            if(i%5==0){
                System.out.println(Thread.currentThread().getName()+"准备让出CPU使用权");
                //当前线程让出cpu占用
                Thread.yield();
            }
        }
        System.out.println(Thread.currentThread().getName()+"执行完毕");
    }

    public static void main(String[] args) {
        new YieldTest();
        new YieldTest();
        new YieldTest();
    }
}

 

线程中断

 java中线程中断是一种线程之间的协作模式,通过设置线程的中断标志并不能直接终止该线程的执行,而是被中断的线程根据中断状态自行处理

  void  interrupt()方法:中断线程,例如,当线程A运行时,线程B可以调用线程A的Interrupt()方法来设置线程A的中断标志为true并立即返回。设置标志仅仅是设置标志,线程A实际并没有被中断,他会继续往下执行;如果线程A因为调用了wait系列函数、join方法或者sleep方法而被阻塞挂起,这时候如果线程B调用线程A的interrupt()方法,线程A会在调用这些方法的地方抛出InterruptedException异常而返回

  boolean  isInterrupted()方法:检测当前线程是否被中断,如果是返回true,如果不是返回false 

public boolean isInterrupted() {
        return isInterrupted(false);
    }

  boolean  interrupted()方法:检测当前线程是否被中断,如果是返回true,如果不是返回false;与isInterrupted()方法不同的是,该方法如果发现当前线程被中断,则会清除中断标志,并且该方法是static方法,可以通过Thread直接调用

 public static boolean interrupted() {
        return currentThread().isInterrupted(true);
    }

  例如: 

public static void main(String[] args) throws Exception{
        Thread threadA=new Thread(new Runnable() {
            @Override
            public void run() {
                while(!Thread.currentThread().isInterrupted()){
                    System.out.println("线程执行中。。。。");
                }
            }
        });
        threadA.start();
        //主线程休眠,以便于线程A的执行
        Thread.sleep(1000);
        System.out.println("中断threadA的执行");
        threadA.interrupt();
        //等待threadA子线程的执行完毕
        threadA.join();
        System.out.println("执行完毕");
    }

  执行结果:

  技术分享图片

 

   代码中,子线程threadA通过检查当前线程是否被中断来控制是否退出循环,主线程在休眠1秒之后,调用了threadA的interrupt()方法设置了子线程中断标志,所以子线程中的循环退出

 

 当线程为了等待某些特定的时间,通常会调用sleep方法、wait系列方法或者join方法来阻塞挂起当前线程,比如一个线程调用了sleep(3000),那么这个线程只有三秒之后才会从阻塞状态变为激活状态,但是有可能3秒内条件早已满足,如果一直等呢,就会浪费时间,所以此时就可以调用interrupt方法强制方法抛出InterruptedException而返回,线程恢复到激活状态

public static void main(String[] args) throws Exception{
        Thread threadA=new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("threadA开始执行");
                try {
                    //子线程睡眠
                    Thread.sleep(200000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程A执行结束");
            }
        });
        threadA.start();
        //主线程休眠,以便于线程A的执行
        Thread.sleep(1000);
        System.out.println("中断threadA的执行");
        threadA.interrupt();
        //等待threadA子线程的执行完毕
        threadA.join();
        System.out.println("执行完毕");
    }

  执行结果:

  技术分享图片

 

  以上代码中,正常情况子线程A睡眠20秒,但是主线程在休眠1秒之后调用threadA的interrupt()方法中断了子线程的执行,此时子线程抛出InterruptedException异常后返回

 

 interrupted()和i是Interrupted()方法的不同

  上代码:

public static void main(String[] args) throws Exception{
        Thread threadA=new Thread(new Runnable() {
            @Override
            public void run() {
                for(;;){}
            }
        });
        threadA.start();
        //主线程休眠,以便于线程A的执行
        Thread.sleep(1000);
        System.out.println("中断threadA的执行");
        threadA.interrupt();
        System.out.println("使用isInterrupted获取中断标志"+threadA.isInterrupted());
        System.out.println("使用interrupted获取中断标志"+Thread.interrupted());
        System.out.println("再次使用isInterrupted获取中断标志"+threadA.isInterrupted());
        threadA.join();
        System.out.println("执行完毕");
    }

 执行结果:

 技术分享图片

 

  第一行输出结果为true表示子线程A已被中断,而第而行输出结果为false,表示当前线程没有被中断,注意,使用Thread.interrupted()获取到的是当前线程的中断情况,而代码中的当前线程是主线程,不是子线程,而设置了中断标志的是子线程,所以主线程并没有被中断,所以结果为false,最后重新获取子线程的依然处于中断状态

 如果将代码修改为:

 public static void main(String[] args) throws Exception{
        Thread threadA=new Thread(new Runnable() {
            @Override
            public void run() {
                while(!Thread.interrupted()){

                }
                System.out.println("获取线程的中断状态"+Thread.currentThread().isInterrupted());
            }
        });
        threadA.start();
        //主线程休眠,以便于线程A的执行
        Thread.sleep(1000);
        System.out.println("中断threadA的执行");
        threadA.interrupt();
        threadA.join();
        System.out.println("执行完毕");
    }

 结果: 由上代码可看出,主线程中调用了threadA.interrupt()中断了子线程,而在子线程中循环条件,判断了是否被中断,可以看出如果调用interrupted()方法清除了中断标志

  技术分享图片

 

 线程的上下文切换

 在多线程编程中,线程个数一般大于CPU个数,而每个CPU同一时刻只能被一个线程使用。为了多线程执行,CPU资源分配采用了时间片轮转的策略,就是说给每个线程分配一个时间片,线程在时间片内占用CPU执行任务。当前线程执行完时间片后,就会处于就绪状态并且让出CPU让其他线程占用;从当前线程的上下文切换到其他线程就叫线程的上下文切换。在线程上下文切换中,为了让切换回去的线程知道上次运行到哪里了,就在线程上下文切换的时候保存当前线程的执行线程,在切换前保存上一个任务的状态,当再次执行时,根据保存的执行现场信息恢复执行

 线程的上下文切换时机有:当前线程的CPU时间片使用完处于就绪状态,当前线程被其他线程中断时候

多线程学习---让出执行权、线程中断

原文:https://www.cnblogs.com/jisha/p/14645061.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!