/**
* 常用的构造方法:
*
* public Thread() { init(null, null, "Thread-" + nextThreadNum(), 0); }
* public Thread(Runnable target) { init(null, target, "Thread-" + nextThreadNum(), 0); }
* public Thread(String name) { init(null, null, name, 0); }
* public Thread(ThreadGroup group, String name) { init(group, null, name, 0); }
* public Thread(Runnable target, String name) { init(null, target, name, 0); }
* public Thread(ThreadGroup group, Runnable target, String name) { init(group, target, name, 0); }
*/
/**
* start()方法使用synchronized关键字修饰,说明start()方法
* 是同步的,它会在启动线程前检查线程的状态,如果不是初始化状态,则直接抛出异常。所以,一个线
* 程只能启动一次,多次启动是会抛出异常的。可以源码探究
*
* 这里,也是面试的一个坑:面试官:
* 【问题一】能不能多次调用Thread类的start()方法来启动线程吗? 答:不能
* 【问题二】多次调用Thread线程的start()方法会发生什么? 答:抛异常
* 【问题三】为什么会抛出异常? 答:如果线程已start(),就已记录它的状态,再次调用判断为不是初始化状态就抛异常
*
* 调用start()方法后,新创建的线程就会处于就绪状态(如果没有分配到CPU执行),当有空闲的CPU
* 时,这个线程就会被分配CPU来执行,此时线程的状态为运行状态,JVM会调用线程的run()方法执行任
* 务。
*/
@Slf4j
public class ThreadTest {
/**
* 常用的构造方法:
*
* public Thread() { init(null, null, "Thread-" + nextThreadNum(), 0); }
* public Thread(Runnable target) { init(null, target, "Thread-" + nextThreadNum(), 0); }
* public Thread(String name) { init(null, null, name, 0); }
* public Thread(ThreadGroup group, String name) { init(group, null, name, 0); }
* public Thread(Runnable target, String name) { init(null, target, name, 0); }
* public Thread(ThreadGroup group, Runnable target, String name) { init(group, target, name, 0); }
*/
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread("importCustomerInfo");
thread1.start();
test();
join();
log.info(">>{}", Thread.currentThread().getName());
}
public static void test() {
// 任务1
Runnable task = () -> {
// 任务逻辑
log.info(">>{}", Thread.currentThread().getName());
};
// 执行任务。指定线程的名字,便于问题定位
Thread thread = new Thread(task, "importCustomerInfo");
thread.start();
/**
* start()方法使用synchronized关键字修饰,说明start()方法
* 是同步的,它会在启动线程前检查线程的状态,如果不是初始化状态,则直接抛出异常。所以,一个线
* 程只能启动一次,多次启动是会抛出异常的。
*
* 这里,也是面试的一个坑:面试官:
* 【问题一】能不能多次调用Thread类的start()方法来启动线程吗? 答:不能
* 【问题二】多次调用Thread线程的start()方法会发生什么? 答:抛异常
* 【问题三】为什么会抛出异常? 答:如果线程已start(),就已记录它的状态,再次调用判断为不是初始化状态就抛异常
*
* 调用start()方法后,新创建的线程就会处于就绪状态(如果没有分配到CPU执行),当有空闲的CPU
* 时,这个线程就会被分配CPU来执行,此时线程的状态为运行状态,JVM会调用线程的run()方法执行任
* 务。
*/
//thread.start(); // 会报错
// 任务2
Runnable task2 = () -> {
log.info(">>>>{}", Thread.currentThread().getName());
};
new Thread(task2, "orderImport").start();
// 任务3
new Thread(() -> {
log.info(">>>{}", Thread.currentThread().getName());
}, "pointImport").start();
}
/**
* 在实际业务场景中,有时,后启动的线程可能需要依赖先启动的线程执行完成才能正确的执行线程中的
* 业务逻辑。此时,就需要确保线程的执行顺序。那如何控制呢?
*
* 通过thread的join()使得线程有序执行,
*
* 为什么可以保证?
* 底层调用wait()方法
* 需要注意的是,调用线程的wait()方法时,会使主线程处于等待状态,等待子线程执行完成后再次向下
* 执行。也就是说,在ThreadSort02类的main()方法中,调用子线程的join()方法,会阻塞main()方法
* 的执行,当子线程执行完成后,main()方法会继续向下执行,启动第二个子线程,并执行子线程的业务
* 逻辑,以此类推。
*/
private static void join() throws InterruptedException {
// 任务1
Runnable task = () -> {
// 任务逻辑
log.info("join1>>{}", Thread.currentThread().getName());
};
// 执行任务。指定线程的名字,便于问题定位
Thread thread = new Thread(task, "importCustomerInfo");
thread.start();
thread.join();
// 任务2
Runnable task2 = () -> {
log.info("join2>>>>{}", Thread.currentThread().getName());
};
Thread orderImport = new Thread(task2, "orderImport");
orderImport.start();
orderImport.join();
// 任务3
Thread pointImport = new Thread(() -> {
log.info("join3>>>{}", Thread.currentThread().getName());
}, "pointImport");
pointImport.start();
pointImport.join();
}
}