线程的常用操作方法


线程的命名和取得

  • 线程的名字是一个至关重要的概念

  • 在Thread类中提供有线程名称的处理

  • 构造方法:public Thread(Runnable target, String name);

  • 设置名字:public final void setName(String name);

  • 取得名字:public final String getName();

    Thread.currentThread().getName()
    
  • 主线程负责处理整体流程,子线程负责处理耗时流程

线程的休眠

  • 在Thread类中定义的休眠方法如下:

    • 休眠:

      public static void sleep(long millis) throws InterruptedException;
      
    • 休眠:

      public static void sleep(long millis, int nanos) throws InterruptedException;
      
  • 在进行休眠的时候可能会产生中断异常“InterruptedException”,中断异常是Exception的子类,所以必须处理。

    public class ThreadDemo {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            // 创建5个线程对象
            for (int num = 0; num < 5; num++) {
                new Thread(() -> {
                    for (int i = 0; i < 10; i++) {
                        System.out.println(Thread.currentThread().getName() + ", i = " + i);
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }, "线程对象 - " + num).start();
            }
    
        }
    }
    
    // 执行结果,5个线程对象一起休眠
    线程对象 - 0, i = 0
    线程对象 - 3, i = 0
    线程对象 - 2, i = 0
    线程对象 - 1, i = 0
    线程对象 - 4, i = 0
    线程对象 - 4, i = 1
    线程对象 - 0, i = 1
    线程对象 - 3, i = 1
    线程对象 - 1, i = 1
    线程对象 - 2, i = 1
    线程对象 - 0, i = 2
    线程对象 - 4, i = 2
    线程对象 - 2, i = 2
    线程对象 - 3, i = 2
    线程对象 - 1, i = 2
    线程对象 - 4, i = 3
    线程对象 - 0, i = 3
    线程对象 - 2, i = 3
    线程对象 - 3, i = 3
    线程对象 - 1, i = 3
    线程对象 - 3, i = 4
    线程对象 - 4, i = 4
    线程对象 - 0, i = 4
    线程对象 - 1, i = 4
    线程对象 - 2, i = 4
    线程对象 - 3, i = 5
    线程对象 - 1, i = 5
    线程对象 - 4, i = 5
    线程对象 - 2, i = 5
    线程对象 - 0, i = 5
    线程对象 - 4, i = 6
    线程对象 - 0, i = 6
    线程对象 - 1, i = 6
    线程对象 - 3, i = 6
    线程对象 - 2, i = 6
    线程对象 - 3, i = 7
    线程对象 - 0, i = 7
    线程对象 - 1, i = 7
    线程对象 - 4, i = 7
    线程对象 - 2, i = 7
    线程对象 - 1, i = 8
    线程对象 - 4, i = 8
    线程对象 - 2, i = 8
    线程对象 - 3, i = 8
    线程对象 - 0, i = 8
    线程对象 - 2, i = 9
    线程对象 - 1, i = 9
    线程对象 - 4, i = 9
    线程对象 - 0, i = 9
    线程对象 - 3, i = 9
    

线程的中断

  • 在Thread类中定义中断执行的处理方法如下:

    • 判断线程是否被中断:

      public boolean isInterrupted();
      
    • 中断线程执行:

      public void interrupt();
      
  • 观察线程的中断处理操作:

    public class ThreadDemo {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            Thread thread = new Thread(() -> {
                System.out.println("【开始学习】开始打代码!");
                try {
                    Thread.sleep(10000);
                    System.out.println("【学习完毕】睡觉!");
                } catch (InterruptedException e) {
                    System.out.println("【怒火冲天】你打扰我打代码!");
                }
            });
            thread.start();
            Thread.sleep(1000);	// 等待一秒中断程序
            // 如果线程没有中断,就执行thread.interrupt()方法中断线程;
            // 当thread.isInterrupted()方法返回true,表示线程被中断;
            // 当thread.isInterrupted()方法返回false,表示线程未被中断;
            if (!thread.isInterrupted()) {
                System.out.println("【朋友来打断你】hello, 起来嗨!");
                thread.interrupt();	// 中断线程
            }
        }
    }
    
    // 执行结果,线程被中断
    【开始学习】开始打代码!
    【朋友来打断你】hello, 起来嗨!
    【怒火冲天】你打扰我打代码!
    

线程的强制执行

  • 当满足于某些条件之后,某一个线程对象将可以一直独占资源移植到该线程的程序执行结束

  • 强制执行的方法:

    public final void join() throws InterruptedException;
    
  • 观察一个没有强制执行的程序:

    public class ThreadDemo {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            Thread mainThread = Thread.currentThread();
            Thread thread = new Thread(() -> {
                for (int i = 1; i <= 10; i++) {
                    System.out.println(Thread.currentThread().getName() + "愉快的玩耍了 " + i + "次!");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
    
            }, "大雄");
            thread.start();
            for (int i = 1; i <= 10; i++) {
                System.out.println(mainThread.getName() + "胖虎玩了 " + i + "次!");
                Thread.sleep(1000);
            }
        }
    }
    
    // 执行结果,可以看到,主线程和子线程是抢着执行的
    大雄愉快的玩耍了 1次!
    main胖虎玩了 1次!
    main胖虎玩了 2次!
    大雄愉快的玩耍了 2次!
    main胖虎玩了 3次!
    大雄愉快的玩耍了 3次!
    main胖虎玩了 4次!
    大雄愉快的玩耍了 4次!
    main胖虎玩了 5次!
    大雄愉快的玩耍了 5次!
    大雄愉快的玩耍了 6次!
    main胖虎玩了 6次!
    大雄愉快的玩耍了 7次!
    main胖虎玩了 7次!
    main胖虎玩了 8次!
    大雄愉快的玩耍了 8次!
    main胖虎玩了 9次!
    大雄愉快的玩耍了 9次!
    main胖虎玩了 10次!
    大雄愉快的玩耍了 10次!
    
  • 再来观察一个强制执行的程序:

    public class ThreadDemo {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            Thread mainThread = Thread.currentThread();
            Thread thread = new Thread(() -> {
                for (int i = 1; i <= 10; i++) {
                    if (i == 5) {
                        try {
                            System.out.println("胖虎一挥拳,给我让开,别挡道!");
                            mainThread.join();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println(Thread.currentThread().getName() + "愉快的玩耍了 " + i + "次!");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
    
            }, "大雄");
            thread.start();
            for (int i = 1; i <= 10; i++) {
                System.out.println(mainThread.getName() + "胖虎玩了 " + i + "次!");
                Thread.sleep(1000);
            }
        }
    }
    
    // 执行结果,可以看到,当i==5时,主线程通过mainThread.join()方法强制执行
    main胖虎玩了 1次!
    大雄愉快的玩耍了 1次!
    main胖虎玩了 2次!
    大雄愉快的玩耍了 2次!
    大雄愉快的玩耍了 3次!
    main胖虎玩了 3次!
    main胖虎玩了 4次!
    大雄愉快的玩耍了 4次!
    main胖虎玩了 5次!
    胖虎一挥拳,给我让开,别挡道!	// 主线程开始强制执行
    main胖虎玩了 6次!
    main胖虎玩了 7次!
    main胖虎玩了 8次!
    main胖虎玩了 9次!
    main胖虎玩了 10次!
    大雄愉快的玩耍了 5次!
    大雄愉快的玩耍了 6次!
    大雄愉快的玩耍了 7次!
    大雄愉快的玩耍了 8次!
    大雄愉快的玩耍了 9次!
    大雄愉快的玩耍了 10次!
    
  • 注意:在进行线程强制执行时,一定要在获取强制执行线程对象之后,才可以执行join()方法调用。

线程的礼让

  • 线程的礼让指的是将资源让出去让别的线程先执行

  • 线程礼让方法:

    public static void yield();
    
  • 使用礼让操作;

    public class ThreadDemo {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            Thread mainThread = Thread.currentThread();
            Thread thread = new Thread(() -> {
                for (int i = 1; i <= 10; i++) {
                    if (i % 5 == 0) {
                        System.out.println("--- 胖虎你先玩!---");
                        Thread.yield();
                    }
                    System.out.println(Thread.currentThread().getName() + "愉快的玩耍了 " + i + "次!");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
    
            }, "大雄");
            thread.start();
            for (int i = 1; i <= 10; i++) {
                System.out.println(mainThread.getName() + "胖虎玩了 " + i + "次!");
                Thread.sleep(1000);
            }
        }
    }
    
    // 执行结果,可以看到每执行到5的倍数的时候,子线程都礼让主线程先执行
    main胖虎玩了 1次!
    大雄愉快的玩耍了 1次!
    大雄愉快的玩耍了 2次!
    main胖虎玩了 2次!
    大雄愉快的玩耍了 3次!
    main胖虎玩了 3次!
    main胖虎玩了 4次!
    大雄愉快的玩耍了 4次!
    --- 胖虎你先玩!---	// 子线程礼让主线程,只礼让当前资源
    main胖虎玩了 5次!
    大雄愉快的玩耍了 5次!
    main胖虎玩了 6次!
    大雄愉快的玩耍了 6次!
    大雄愉快的玩耍了 7次!
    main胖虎玩了 7次!
    main胖虎玩了 8次!
    大雄愉快的玩耍了 8次!
    main胖虎玩了 9次!
    大雄愉快的玩耍了 9次!
    --- 胖虎你先玩!---
    main胖虎玩了 10次!
    大雄愉快的玩耍了 10次!
    
  • 每一次执行yield()方法都只会礼让当前资源

线程优先级

  • 从理论上来讲线程的优先级越高越有可能先执行(注意是有可能)

  • 在Thread类中提供了两个关于优先级的方法:

    • 设置优先级:

      public final void setPriority(int newPriority);
      
    • 获取优先级:

      public final int getPriority();
      
  • 在Thread类里面定义了三个优先级常量:

    • 最高优先级:

      public static final int MAX_PRIORITY;	// (MAX_PRIORITY = 10)
      
    • 中等优先级:

      public static final int NORM_PRIORITY;	// (MAX_PRIORITY = 5)
      
    • 最低优先级:

      public static final int MIN_PRIORITY;	// (MAX_PRIORITY = 1)
      
  • 观察优先级:

    public class ThreadDemo {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            Thread myThread = new Thread(() -> {
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().getName() + "正在执行");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            Thread threadA = new Thread(myThread, "线程A");
            Thread threadB = new Thread(myThread, "线程B");
            Thread threadC = new Thread(myThread, "线程C");
    
            threadA.setPriority(Thread.NORM_PRIORITY);	// 线程A设置中等优先级
            threadB.setPriority(Thread.NORM_PRIORITY);	// 线程B设置中等优先级
            threadC.setPriority(Thread.MAX_PRIORITY);	// 线程C设置最高优先级
    
            threadA.start();
            threadB.start();
            threadC.start();
        }
    }
    
    // 执行结果,可以看到并不一定优先级最高的先执行
    线程A正在执行	// A先执行,A为中等优先级
    线程C正在执行
    线程B正在执行
    线程A正在执行
    线程B正在执行
    线程C正在执行
    线程A正在执行
    线程B正在执行
    线程C正在执行
    线程C正在执行	// C先执行,C为最高优先级
    线程A正在执行
    线程B正在执行
    线程C正在执行
    线程A正在执行
    线程B正在执行
    
  • 作者:周海林(联系作者)
  • 发表时间:2020-04-12
  • 版权声明:自由转载-非商用-非衍生-周海林贼帅
  • 加作者微信:请在文末添加作者微信

评论