? ? 1、线程休眠
? ? (1)sleep()
? ?
? ? ? ? 如果需要让当前正在执行的线程暂停一段时间,并进入阻塞状态(Timed_Waiting),则可以通过调用Thread类的静态sleep()方法来实现。
? ?
? ? ? ? static void sleep(long millis):让当前正在执行的线程暂停millis毫秒,并进入阻塞状态,该方法受到系统计时器和线程调度器的精度与准确度的影响。
? ? ? ? static void sleep(long millis,int nanos):让当前正在执行的线程暂停millis毫秒加nanos毫微秒,并进入阻塞状态,该方法受到系统计时器和线程调度器的精度与准确度的影响。
? ? ? ? 当前线程调用 sleep()方法进入阻塞状态后,在其睡眠时间段内,该线程不会获得执行的机会,即使系统中没有其他可执行的线程,处于sleep()中的线程也不会执行,因此sleep()方法常用来暂停程序的执行。
/**
?* sleep()方法练习
? ?*/
? ?public class SleepDemo1 {
? ?public static void main(String[] args) {
? ? ? ?Thread t1 = new Thread(()->{
? ? ? ? ? while(true){
? ? ? ? ? ? ? ?System.out.println(true);
? ? ? ? ? ? ? ?try {
? ? ? ? ? ? ? ? ? ?Thread.sleep(3000);
? ? ? ? ? ? ? ?} catch (InterruptedException e) {
? ? ? ? ? ? ? ? ? ?throw new RuntimeException(e);
? ? ? ? ? ? ? ?}
? ? ? ? ? }
? ? ? ?});
? ? ? ?//t1不调用start()方法 只调用run()方法时
? ? ? ?//此时只有main线程运行 调用sleep()休眠的是mian线程
? ? ? ?t1.run();
? ? ? ?System.out.println("main线程休眠");
? ?}
? ?}
/**
?* sleep()方法练习
? ?*/
? ?public class SleepDemo2 {
? ?public static void main(String[] args) throws InterruptedException {
? ? ? ?Thread t2 = new Thread(()->{
? ? ? ? ? ?while(true){
? ? ? ? ? ? ? ?System.out.println(true);
? ? ? ? ? ? ? ?try {
? ? ? ? ? ? ? ? ? ?//t2线程休眠 无法在休眠时间段内唤醒线程
? ? ? ? ? ? ? ? ? ?Thread.sleep(1000);
? ? ? ? ? ? ? ?} catch (InterruptedException e) {
? ? ? ? ? ? ? ? ? ?throw new RuntimeException(e);
? ? ? ? ? ? ? ?}
? ? ? ? ? ?}
? ? ? ?});
? ? ? ?t2.start();
? ? ? ?//休眠主线程 确保t2线程执行
? ? ? ?TimeUnit.SECONDS.sleep(3);
? ? ? ?//sleep()休眠后 t2线程的状态为TIME_WAITING
? ? ? ?System.out.println(t2.getState());//TIMED_WAITING
? ?}
? ?}
/**
?* sleep()方法练习
? ?*/
? ?public class SleepDemo3 {
? ?public static void main(String[] args) throws InterruptedException {
? ? ? ?Thread t3 = new Thread(()->{
? ? ? ? ? ?while(true){
? ? ? ? ? ? ? ?System.out.println(true);
? ? ? ? ? ?}
? ? ? ?});
? ? ? ?t3.start();
? ? ? ?//注意 sleep()是类方法 能使用创建对象的方式调用,但是不会有休眠效果,所以不能使用这种方式调用sleep()方法
? ? ? ?t3.sleep(1000);
? ? ? ?//休眠主线程 确保t2线程执行
? ? ? ?TimeUnit.SECONDS.sleep(3);
? ? ? ?//此时,t2线程不会被休眠
? ?}
? ?}
/**
?* Interrupt()方法
? ?*/
? ?public class InterruptedDemo {
? ?public static void main(String[] args) {
? ? ? ?Thread t4 = new Thread(()->{
? ? ? ? ? ?while (true){
? ? ? ? ? ? ? ?System.out.println(true);
? ? ? ? ? ?}
? ? ? ?});
? ? ? ?t4.start();
? ? ? ?//调用interrupt()方法无法中断线程
? ? ? ?//只能采用先标记线程中断
? ? ? ?//然后通过Thread.interrupted();判断线程状态是否为中断状态
? ? ? ?//若为true则通过抛异常的方式中断程序
? ? ? ?t4.interrupt();
? ?}
? ?}
? ?(2) LockSupport类
? ?
? ? LockSupport是JUC提供的一个线程阻塞与唤醒的工具类,该工具类可以让线程在任意位置阻塞和唤醒,其所有的方法都是静态方法。
/**
?* park()方法练习
? ?*/
? ?public class LockSupportDemo1 {
? ?public static void main(String[] args) throws InterruptedException {
? ? ? ?Thread t1 = new Thread(()->{
? ? ? ? ? ?System.out.println("t1线程开始休眠");
? ? ? ? ? ?//无休止休眠 t1线程为阻塞态 为Waiting
? ? ? ? ? ?LockSupport.park();
? ? ? ? ? ?System.out.println("t1线程结束休眠");
? ? ? ?});
? ? ? ?//启动线程t1
? ? ? ?t1.start();
? ? ? ?//休眠主线程,让线程t1能顺利执行
? ? ? ?TimeUnit.SECONDS.sleep(3);
? ? ? ?System.out.println(t1.getState());//Waiting
? ?}
? ?}
/**
?* unpark()方法练习
? ?*/
? ?public class LockSupportDemo2 {
? ?public static void main(String[] args) throws InterruptedException {
? ? ? ?Thread t2 = new Thread(()->{
? ? ? ? ? ?System.out.println("t1线程开始休眠");
? ? ? ? ? ?//休眠指定的时间 休眠后可以在休眠时间段内重新被唤醒 比较灵活
? ? ? ? ? ?LockSupport.parkNanos(10000000000L);
? ? ? ? ? ?System.out.println("t1线程结束休眠");
? ? ? ?});
? ? ? ?//启动线程t2
? ? ? ?t2.start();
? ? ? ?//休眠主线程,让线程t2能顺利执行
? ? ? ?TimeUnit.SECONDS.sleep(3);
? ? ? ?LockSupport.unpark(t2);
? ? ? ?System.out.println(t2.getState());//Time_Waiting(不定)
? ? ? ?System.out.println("线程被唤醒");
? ? ? ?System.out.println(t2.getState());//TERMINATED
? ?}
? ?}
? ?当调用park()方法时,会让线程进入WAITING状态,调用parkNanos(long nanos)方法时,线程会进入TIMED_WAITING状态
/**
?* unpark()方法练习
? ?*/
? ?public class LockSupportDemo2 {
? ?public static void main(String[] args) throws InterruptedException {
? ? ? ?Thread t2 = new Thread(()->{
? ? ? ? ? ?System.out.println("t1线程开始休眠");
? ? ? ? ? ?//休眠指定的时间 休眠后可以在休眠时间段内重新被唤醒 比较灵活
? ? ? ? ? ?LockSupport.parkNanos(10000000000L);
? ? ? ? ? ?System.out.println("t1线程结束休眠");
? ? ? ?});
? ? ? ?//启动线程t2
? ? ? ?t2.start();
? ? ? ?//休眠主线程,让线程t2能顺利执行
? ? ? ?TimeUnit.SECONDS.sleep(3);
? ? ? ?LockSupport.unpark(t2);
? ? ? ?System.out.println(t2.getState());//Time_Waiting(不定)
? ? ? ?System.out.println("线程被唤醒");
? ? ? ?System.out.println(t2.getState());//TERMINATED
? ?}
? ?}
? ?LockSupport.park()和Thread.sleep()的区别:
? ?1、Thread.sleep()无法从外部唤醒。只能自己醒过来;而被LockSupport.park()方法阻塞的线程可以通过调用LockSupport.unpark()方法去唤醒。
? ?2、被Thread.sleep()、LockSupport.park()方法所阻塞的线程有一个特点,当被阻塞线程的Thread.interrupt()方法调用时,被阻塞线程的中断标志将被设置,该线程将被唤醒。不同的是,二者对中断信号的响应方式不同:LockSuppport.park()方式不会抛出InterruptedExcepton异常,仅仅设置了线程的中断标志;而Thread.sleep()方法会抛出InterruptedException异常
? ?3、与Thread.sleep()相比,调用LockSupport.park()更能精准、更加灵活地阻塞、唤醒指定线程。
? ?2、线程让步
? ?yield()方法是一个和 sleep()方法有点相似的方法,它也是 Thread 类提供的一个静态方法,它也可以让当前正在执行的线程暂停,但它不会阻塞该线程,它只是将该线程转入就绪状态。
? ?yield()只是让当前线程暂停一下,让系统的线程调度器重新调度一次,线程调度器会从线程就绪队列里获取一个线程优先级高的线程,当然完全可能的情况是:当某个线程调用了yield()方法暂停之后,线程调度器又将其调度出来重新执行。
? ?当某个线程调用了yield()方法暂停之后,只有优先级与当前线程相同,或者优先级比当前线程更高的处于就绪状态的线程才会获得执行的机会。下面程序使用yield()方法来让当前正在执行的线程暂停。
/**
?* yield()方法练习
? ?*/
? ?public class YieldDemo {
? ?public static void main(String[] args) {
? ? ? ?Thread t1 = new Thread(()->{
? ? ? ? ? ?for (int i = 1; i < 30; i++) {
? ? ? ? ? ? ? ?System.out.println(Thread.currentThread().getName()+"=============="+i);
? ? ? ? ? ? ? ?if(i%10==0){
? ? ? ? ? ? ? ? ? ?//调用yield方法让t1线程暂停
? ? ? ? ? ? ? ? ? ?Thread.yield();
? ? ? ? ? ? ? ?}
? ? ? ? ? ?}
? ? ? ?},"t1");
? ? ? ?Thread t2 = new Thread(()->{
? ? ? ? ? ?for (int i = 0; i < 30; i++) {
? ? ? ? ? ? ? ?System.out.println(Thread.currentThread().getName()+">>>"+i);
? ? ? ? ? ?}
? ? ? ?},"t2");
? ? ? ?//yield之后,有可能原来执行的线程继续获得执行的机会
? ? ? ?//为t1线程设置优先级
? ? ? ?t1.setPriority(10);
? ? ? ?//启动t1线程
? ? ? ?t1.start();
? ? ? ?//为t2线程设置优先级
? ? ? ?t2.setPriority(1);
? ? ? ?//启动t2线程
? ? ? ?t2.start();
? ? ? ?//优先级大的线程不一定先执行,而是执行概率大
? ? ? ?for (int i = 0; i < 30; i++) {
? ? ? ? ? ?System.out.println(Thread.currentThread().getName()+">>>"+i);
? ? ? ?}
? ?}
? ?}
? ?3、线程优先级
? ?每个线程执行时都具有一定的优先级,优先级高的线程获得较多的执行机会,而优先级低的线程则获得较少的执行机会。每个线程默认的优先级都与创建它的父线程的优先级相同,在默认情况下,main线程具有普通优先级,由main线程创建的子线程也具有普通优先级。
? ?Thread类提供了setPriority(int newPriority)、getPriority()方法来设置和返回指定线程的优先级,其中setPriority()方法的参数可以是一个整数,范围是1~10之间,也可以使用Thread类的如下3个静态常量。
? ?MAX_PRIORITY:其值是10。
? ?MIN_PRIORITY:其值是1。
? ?NORM_PRIORITY:其值是5。
/**
?* 优先级练习
? ?*/
? ?public class PriorityDemo {
? ?public static void main(String[] args) throws InterruptedException {
? ? ? ?//定义存放线程的数组
? ? ? ?MyThread[] myThreads = new MyThread[10];
? ? ? ?int length = myThreads.length;
? ? ? ?//优先级为1<-->10 循环需要从1开始
? ? ? ?for (int i = 1; i <=length; i++) {
? ? ? ? ? ?//创建线程
? ? ? ? ? ?myThreads[i-1] = new MyThread();
? ? ? ? ? ?//分别创建线程优先级
? ? ? ? ? ?myThreads[i-1].setPriority(i);
? ? ? ? ? ?//启动线程
? ? ? ? ? ?myThreads[i-1].start();
? ? ? ?}
? ? ? ?//休眠主线程 让创建的线程得以执行
? ? ? ?TimeUnit.SECONDS.sleep(3);
? ? ? ?for (int i = 0; i < length; i++) {
? ? ? ? ? ?//停止线程
? ? ? ? ? ?myThreads[i].stop();
? ? ? ?}
? ?}
? ?}
? ?优先级的继承
? ?/**
?* 优先级练习2
? ?*/
? ?public class PriorityDemo2 {
? ?public static void main(String[] args) {
? ? ? ?Thread thread = new Thread(()->{
? ? ? ? ? ?System.out.println("线程thread执行");
? ? ? ?},"thread");
? ? ? ?Thread main = Thread.currentThread();
? ? ? ?System.out.println(main.getState());
? ? ? ?System.out.println(main.getName()+"线程的优先级:"+main.getPriority());
? ? ? ?//在main线程中创建thread线程,thread线程的优先级与main线程一致
? ? ? ?thread.start();
? ? ? ?System.out.println(thread.getName()+"线程的优先级:"+thread.getPriority());
? ?}
? ?}
?