方法

void **[setPriority](https://www.matools.com/file/manual/jdk_api_1.8_google/java/lang/Thread.html#setPriority-int-)**(int newPriority)更改此线程的优先级。
static void **[sleep](https://www.matools.com/file/manual/jdk_api_1.8_google/java/lang/Thread.html#sleep-long-)**(long millis)使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行),具体取决于系统定时器和调度程序的精度和准确性。
void **[join](https://www.matools.com/file/manual/jdk_api_1.8_google/java/lang/Thread.html#join-long-)**(long millis)等待这个线程死亡最多 millis毫秒。
static void **[yield](https://www.matools.com/file/manual/jdk_api_1.8_google/java/lang/Thread.html#yield--)**()对调度程序的一个暗示,即当前线程愿意产生当前使用的处理器。
void **[interrupt](https://www.matools.com/file/manual/jdk_api_1.8_google/java/lang/Thread.html#interrupt--)**()中断这个线程。
boolean **[isAlive](https://www.matools.com/file/manual/jdk_api_1.8_google/java/lang/Thread.html#isAlive--)**()测试这个线程是否活着。
long **[getId](https://www.matools.com/file/manual/jdk_api_1.8_google/java/lang/Thread.html#getId--)**()返回此线程的标识符。

**

停止线程

  • 不推荐使用:stop、destroy方法
  • 推荐线程自己停止
  • 使用标志位进行中止变量,当flag=false,则线程中止运行 ; 或使用有限次的循环代替死循环
  1. public class ThreadBase04 implements Runnable {
  2. // 设置标识位
  3. private boolean flag = true;
  4. // 设置一个公开的方法停止线程,转换标识位
  5. public void stop() {
  6. this.flag = false;
  7. }
  8. @Override
  9. public void run() {
  10. int i = 0;
  11. // 线程体内使用该标识进行控制
  12. while (flag) {
  13. System.out.println("hello! " + i++);
  14. }
  15. }
  16. public static void main(String[] args) {
  17. ThreadBase04 threadBase04 = new ThreadBase04();
  18. new Thread(threadBase04).start();
  19. for (int i = 0; i < 500; i++) {
  20. System.out.println(Thread.currentThread().getName() + "运行 : " + i);
  21. }
  22. threadBase04.stop();
  23. }
  24. }

线程休眠

  • 存在异常 InterruptedException
  • sleep到达时间后进入就绪状态,等待CPU资源再执行。
  • 可以用于模拟网络时延、倒计时
  • 每个对象都有一个锁,sleep不会释放锁

后面都用JUC的TimeUnit进行休眠

  1. Thread.sleep(1000); // 休眠一秒钟

线程礼让 yield

  • 让当前正在执行的线程暂停,但是不阻塞
  • 将线程从运行状态转为就绪状态(释放CPU资源)
  • 让cpu重新调度,礼让不一定成功,看CPU。 ```java public class TestYield { public static void main(String[] args) {
    1. MyYield myYield = new MyYield();
    2. new Thread(myYield, "a").start();
    3. new Thread(myYield, "b").start();
    } }

class MyYield implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName() + “ 线程开始执行”); // 礼让 Thread.yield(); System.out.println(Thread.currentThread().getName() + “ 线程结束执行”); } }

礼让不一定成功:

a 线程开始执行 a 线程结束执行 b 线程开始执行 b 线程结束执行


a 线程开始执行 b 线程开始执行 a 线程结束执行 b 线程结束执行



<a name="TEnqG"></a>
# join

- 合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞。 哪个线程调用了join方法,当前线程就等待哪个线程执行完毕。
- 类似于插队
```java
public class TestJoin implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + " 线程执行 " + i);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        TestJoin testJoin = new TestJoin();
        Thread vip = new Thread(testJoin, "vip");
        vip.start();

        for (int i = 0; i < 200; i++) {
            System.out.println(Thread.currentThread().getName() + " 线程执行 " + i);
            if (i == 70) {
                // 主线程被阻塞,等待vip线程执行完之后才会执行主线程
                vip.join();
            }
        }
    }
}

观测线程状态

  • NEW
    尚未启动的线程处于此状态。
  • RUNNABLE
    在Java虚拟机中执行的线程处于此状态。
  • BLOCKED
    被阻塞等待监视器锁定的线程处于此状态。
  • WAITING
    正在等待另一个线程执行特定动作的线程处于此状态。
  • TIMED_WAITING
    正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。
  • TERMINATED
    已退出的线程处于此状态。
    Thread thread = new Thread(() -> {
              for (int i = 0; i < 5; i++) {
                  try {
                      Thread.sleep(1000);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
                  System.out.println(".....");
              }
          });
          // 观察 NEW状态
          Thread.State state = thread.getState();
    

线程优先级

  • 线程调度器按照优先级决定应该调度哪个线程来执行。效果不明显,优先级高也不一定先执行
  • 范围1-10
    • Thread.MIN_PRIORITY=1
    • Thread.MAX_PRIORITY=10
    • Thread.NORM_PRiORITY=5
  • getPriority() 或者 setPriority()

守护线程

  • 线程分为用户线程和守护线程
    • 虚拟机必须确保用户线程执行完毕
    • 虚拟机不用等待守护线程执行完毕,例如:后台记录操作日志、监控内存、垃圾回收
Thread thread = new Thread(...);
thread.setDaemon(true); // 默认为false,代表用户线程
thread.start();

判断线程是否活动

thread.isAlive()
判断该线程是否处于活动状态,活动状态就是线程已启动并且尚未终止。

获取线程id

thread.getId()
main线程的id是1,线程结束后,该id可以被重新赋值给其他线程。
但是在运行期间,线程的id是唯一的。

Object.wait

使线程状态从RUNNABLE转换为WAITING

调用wait()方法前线程必须持有对象的锁。 线程调用wait()方法时,会释放当前的锁,直到有其他线程调用notify()/notifyAll()方法唤醒等待锁的线程。

需要注意的是,其他线程调用notify()方法只会唤醒单个等待锁的线程,如有有多个线程都在等待这个锁的话不一定会唤醒到之前调用wait()方法的线程。

同样,调用notifyAll()方法唤醒所有等待锁的线程之后,也不一定会马上把时间片分给刚才放弃锁的那个线程,具体要看系统的调度。

wait和sleep的区别

  1. 来自不同的类:wait来自于Object类,sleep来自于Thread类
  2. 锁的释放:wait释放锁,sleep不释放锁
  3. 使用的范围不同:sleep可以在任意地方使用,wait只能在同步代码块中使用