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