线程的常用方法

1 run()和start()

示例代码

import lombok.extern.slf4j.Slf4j;

/**
 * @author : look-word
 * 2022-08-13 15:31
 **/
@Slf4j
public class C1_RunAndStart {
    public static void main(String[] args) {
        Thread thread = new Thread() {
            @Override
            public void run() {
                log.info("当前线程 {} ", Thread.currentThread().getName());
            }
        };
        thread.run();
        thread.start();
    }
}

线程的常用方法-LMLPHP

2 sleep

  1. 调用 sleep 会让当前线程从 Running 进入 Timed Waiting 状态(阻塞)
  2. 其它线程可以使用 interrupt 方法打断正在睡眠的线程,这时 sleep 方法会抛出 InterruptedException
  3. 睡眠结束后的线程未必会立刻得到执行
  4. 建议用 TimeUnit 的 sleep 代替 Thread 的 sleep 来获得更好的可读性

3 yield

  1. 调用 yield 会让当前线程从 Running 进入 Runnable 就绪状态,然后调度执行其它线程
  2. 具体的实现依赖于操作系统的任务调度器

4 join

示例代码

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

/**
 * @author : look-word
 * 2022-08-13 16:34
 **/
@Slf4j
public class C3_Join {
    static int num = 0;
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            try {
                TimeUnit.MILLISECONDS.sleep(1000); // 使线程睡眠
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            num =10;
        },"t1");
        t1.start();
//        t1.join();
        log.info("num :{}",num);
    }
}
// 执行结果 会先输出num的值 程序不会立马结束运行。(异步)
16:50:39.034 [main] INFO c_常用方法.C3_Join - num :0
// 可以看到 上面的join方法是注释掉的。 我们给它放开之后的执行结果。会等待(同步)
16:52:40.783 [main] INFO c_常用方法.C3_Join - num :10

示例代码2

        Thread t1 = new Thread(() -> {
            try {
                TimeUnit.MILLISECONDS.sleep(2000); // 使线程睡眠
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            num =10;
        },"t1");
        log.info("start。。。");
        t1.start();
        t1.join(1000); // 等待具体的毫秒数
        log.info("num :{}",num);

5 interrupt

示例代码1

        Thread t1 = new Thread(() -> {
            try {
                Thread.sleep(1000);   // 睡眠t1线程
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        t1.start();
        Thread.sleep(10);  // 睡眠主线程
        t1.interrupt(); // 打断t1线程
        log.debug("{}的打断状态{}", t1.getName(), t1.isInterrupted());

线程的常用方法-LMLPHP

示例代码2

    /**
     * 打断正常运行的线程
     */
    private static void test2() throws InterruptedException {
        Thread t1 = new Thread(() -> {
            while (true){
                log.info("{} 线程 running。。",Thread.currentThread().getName());
                if (Thread.currentThread().isInterrupted()){ // 是否被打断
                    break;
                }
            }
        },"t1");
        t1.start();
        t1.interrupt(); // 打断线程
        log.debug("{}的打断状态{}", t1.getName(), t1.isInterrupted());
    }

线程的常用方法-LMLPHP

终止模式之两阶段终止模式

线程的常用方法-LMLPHP

代码实现

import lombok.extern.slf4j.Slf4j;

/**
 * @author : look-word
 * 2022-08-13 18:15
 **/
public class 两极阶段终止模式 {
    public static void main(String[] args) throws InterruptedException {
        Monitor monitor = new Monitor();
        monitor.start(); // 启动监控程序
        Thread.sleep(3500);
        monitor.stop(); // 停止监控程序
    }

}
@Slf4j
class Monitor{ // 监控程序
    Thread monitor;
    // 启动监控线程
    public void start(){
        monitor = new Thread(() ->{
            while (true){
                Thread current = Thread.currentThread();
                if (current.isInterrupted()){
                    log.error("料理后事 结束!");
                    break;
                }
                try {
                    Thread.sleep(1000);
                    log.debug("执行监控记录!!");
                } catch (InterruptedException e) {
                    // 重写设置打断
                    Thread.currentThread().interrupt();
                    e.printStackTrace();
                }
            }
        });
        monitor.start(); // 启动监控线程
    }

    // 停止监控线程
    public void stop(){
        monitor.interrupt(); // 打断线程
    }
}

6 pack

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.locks.LockSupport;

/**
 * join 会使所有线程等待 (同步)
 * LockSupport.park(); 只会使当前线程等待 (异步)
 * @author : look-word
 * 2022-08-13 21:02
 **/
@Slf4j
public class C5_Park {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            log.debug("pack...");
            log.debug("打断状态前:{}", Thread.currentThread().isInterrupted());
            LockSupport.park();  // 使当前线程等待
            log.debug("unPark...");
            log.debug("打断状态后:{}", Thread.currentThread().isInterrupted());
        }, "t1");
        t1.start();
        Thread.sleep(500);
        // 这里会等500ms 立即执行
        log.debug("打断状态:{}", Thread.currentThread().isInterrupted());
        t1.interrupt(); // 打断线程
    }
}

结果

21:17:46.920 [t1] DEBUG c_常用方法.C5_Park - pack...
21:17:46.923 [t1] DEBUG c_常用方法.C5_Park - 打断状态前:false
21:17:47.422 [main] DEBUG c_常用方法.C5_Park - 打断状态:false
21:17:47.422 [t1] DEBUG c_常用方法.C5_Park - unPark...
21:17:47.422 [t1] DEBUG c_常用方法.C5_Park - 打断状态后:true
08-14 14:04