线程常用方法

291 阅读2分钟

start

启动一个线程、在新的线程里执行run方法中的代码。 start 方法只是让线程进入就绪状态,cpu的时间片可能还没分给他,每个线程的start() 只能调用一次,调用多次会报IllegalThreadState异常

run

在构造Thread的时候传递了Runable 参数,线程启动会调用Runable中的run方法。否则不会执行任何操作,但可以创建Thread 的子类,覆盖默认行为。

sleep 方法

  • 调用sleep 方法 会让当前线程从 RUNNING 进入 TIMED_WAITING 状态(不可能获得时间片,不占用cpu资源)
  • 其他线程可以调用 interrupt 方法 打断正在睡眠的线程,这时 sleep 会抛出 InterruptedException
  • 睡眠结束后的线程未必立刻得到执行(睡醒了不一定能立刻获得cpu的使用权)
  • 建议使用 TimeUnitsleep 方法,可以获得更好的可读性。

小应用 : 防止 CPU 占用 100%
轮询处理 (复习才理解这种轮询~)
单核下 一直 while (true) 占用 cpu 100%

while(true) {
    try {Thread.sleep(100);}
    catch(Exception e) {}
}

yield 方法

  • 会让线程从Runing 进入 RUNABLE 状态(有机会获得时间片),然后调度其他线程。
  • 具体的实现依赖于操作系统的任务调度器。
  • 他几乎没有等待时间。

线程优先级

方法 : setPriority(int)

 public final static int MIN_PRIORITY = 1; // 最小
 public final static int NORM_PRIORITY = 5; // 普通优先级
 public final static int MAX_PRIORITY = 10; // 最大优先级

需要注意的是,他仅仅只是一个考量,调度器可以忽略它。
cpu忙的时候,优先级较高的会获得更多时间片。cpu闲的时候,优先级几乎就被忽略了。

join 方法

public class JoinTest {
    static int r ;

    public static void main(String[] args) {
            test1();
        System.out.println(r);
    }

    private static void test1(){
        new Thread(()->{
            try {
                TimeUnit.MILLISECONDS.sleep(1);
                r = 10;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

    }
}

分析 :

  • 主线程和t1并行执行,t1要1ms后才能算出r=10; 解决方法:
  • sleep() 不太好 : 不好把控计算时间,实际开发中 并不会明确知道 计算时间。
public static void main(String[] args) throws InterruptedException {
        test1();
        TimeUnit.MILLISECONDS.sleep(1);
    System.out.println(r);
}
  • join() 解决 : join 等待线程run方法计算任务结束。 即线程死亡。

在使用 join 之前,保证前面的代码是异步的。调用 join之后, 阻塞主线程了,这时候是同步的等待t1 线程。 join(long) 参数 时间到了终止等待。

interrupt 线程的正确终止

打断阻塞状态的线程

即断 sleep、wait、join 的线程。 在打断后,打断标记会被清空

打断运行状态的线程

打断标志位 终止线程运行。

public static void main(String[] args) throws InterruptedException {
   Thread t1 = new Thread(() -> {
       while (true){
           Thread thread = Thread.currentThread();
           boolean interrupted = thread.isInterrupted();
           if (interrupted) {break;}
       }
   });

    Thread.sleep(1000);
    t1.interrupt();
}