
Thread 类,重写 run()/**
* 创建线程方式一:继承Thread类,重写run()
*/
class MyThread extends Thread {
@Override
public void run() {
// ...
}
}
public class demo1 {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
}
}Runnable 接口,重写 run(),然后构造 Thread 进行传参/**
* 创建线程方式二:实现Runnable接口,重写run(),然后传给Thread
*/
class MyRunnable implements Runnable {
@Override
public void run() {
// ...
}
}
public class demo2 {
public static void main(String[] args) {
// 传给Thread,同时也可以给线程命名
Thread t = new Thread(new MyRunnable(), "MyThread");
t.start();
}
}Thread,重写 run()/**
* 创建线程方式三:匿名内部类继承Thread,重写run()
*/
public class demo3 {
public static void main(String[] args) {
Thread t = new Thread() {
public void run() {
// ...
}
};
t.start();
}
}Runnable,重写 run()/**
* 创建线程方式四:匿名内部类实现Runnable,重写run()
*/
public class demo4 {
public static void main(String[] args) {
Runnable myrunnable = new Runnable() {
@Override
public void run() {
// ...
}
};
Thread t = new Thread(myrunnable);
t.start();
}
}lambda 表达式创建 Thread 对象(推荐⭐⭐⭐)/**
* 创建线程方式五:lambda表达式创建Thread对象,顺便命名
*/
public class demo5 {
public static void main(String[] args) {
Thread t = new Thread(() -> {
// ...
}, "MyThread");
t.start();
}
}Thread 类,直接使用 this 就表示当前线程对象的引用。Runnable 接口,this 表示的是 MyRunnable 的引用,需要使用 Thread.currentThread() 来获取当前线程对象。jconsole 程序观察线程在 jdk 的 bin 目录中有一个 jconsole 程序,打开然后连接到对应的 java 程序,就能看到对应的程序信息,比如内存、线程等情况,如下图所示:

Thread 类及常见方法方法名 | 返回类型 | 功能描述 |
|---|---|---|
Thread() | void | 构造一个新线程,但不与任何 Runnable 对象关联。(线程不会自动启动,需要调用 start() 方法来启动线程) |
Thread(Runnable target) | void | 构造一个新线程,并与指定的 Runnable 对象关联。 |
Thread(Runnable target, String name) | void | 构造一个新线程,并与指定的 Runnable 对象关联,同时设置线程的名称。 |
Thread(String name) | void | 构造一个新线程,不与任何 Runnable 对象关联,但设置线程的名称。 |
static Thread currentThread() | Thread | 返回当前正在执行的线程对象 |
void start() | void | 启动线程,使线程进入就绪状态,等待调度器调度后执行run()方法。 如果线程已经启动,再次调用 start() 会抛出 IllegalThreadStateException。 |
void run() | void | 线程的入口点,通常需要重写以实现线程的具体逻辑。如果线程是通过 Thread(Runnable) 构造的,则会调用 Runnable 的 run() 方法。如果不重写,该方法默认为空实现。 |
void join() | void | 等待当前线程终止。调用该方法的线程会阻塞,直到被调用 join() 的线程执行完毕。如果线程已经终止,则立即返回。 |
void join(long millis) | void | 等待当前线程终止,最多等待指定的毫秒数。如果线程在指定时间内结束,则调用该方法的线程会继续执行。如果线程在指定时间内未结束,则抛出 InterruptedException。 |
void join(long millis, int nanos) | void | 等待当前线程终止,最多等待指定的毫秒数和纳秒数。精确控制等待时间,如果线程在指定时间内结束,则调用该方法的线程会继续执行。 |
(下面三个中断相关的方法,可以看看表格后面的注意事项!) | ||
void interrupt() | void | 中断线程。如果线程正在休眠或阻塞,不仅会设置中断标志为 true,还会抛出 InterruptedException;如果线程正在运行,则只会设置中断标志为 true。 |
boolean isInterrupted() | boolean | 检查线程是否被中断,如果线程被中断了,则返回 true,否则返回 false。不设置中断标志。 |
static boolean interrupted() | boolean | 检查当前线程是否被中断,如果当前线程被中断了,则返回 true,并清除中断状态,即设置中断标志为 false。 |
void sleep(long millis) | void | 使当前线程暂停执行指定的毫秒数。调用该方法的线程会进入休眠状态,不会占用 CPU 资源。如果线程在休眠期间被中断,会抛出 InterruptedException。 |
void sleep(long millis, int nanos) | void | 使当前线程暂停执行指定的毫秒数和纳秒数。精确控制线程的休眠时间。如果线程在休眠期间被中断,会抛出 InterruptedException。 |
void yield() | void | 暂停当前线程,让其他具有相同优先级的线程运行。线程调度器会重新调度线程,但不保证其他线程一定会运行。 |
void setPriority(int priority) | void | 设置线程的优先级,优先级范围为 1(最低)到 10(最高),默认为 5。优先级高的线程可能会获得更多 CPU 时间。 |
int getPriority() | int | 获取线程的优先级,返回线程的优先级值。 |
void setName(String name) | void | 设置线程的名称,便于调试和监控。 |
String getName() | String | 获取线程的名称,返回线程的名称字符串。 |
void setDaemon(boolean on) | void | 设置线程为守护线程或用户线程。守护线程在所有用户线程结束后自动退出。 |
boolean isDaemon() | boolean | 检查线程是否为守护线程,如果是守护线程,返回 true。 |
State getState() | State | 获取线程的状态,返回线程的当前状态(如新建、运行、阻塞等)。 |
boolean isAlive() | boolean | 检查线程是否处于活动状态,如果线程已经启动且尚未终止,返回 true。 |
void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) | void | 设置线程的未捕获异常处理器,用于处理线程中未捕获的异常。 |
UncaughtExceptionHandler getUncaughtExceptionHandler() | UncaughtExceptionHandler | 获取线程的未捕获异常处理器,返回设置的异常处理器对象。 |
static void dumpStack() | void | 打印当前线程的堆栈跟踪,通常用于调试。 |
💥注意事项:
run() 只是注册了线程要做的动作,start() 才是真的启动线程。interrupt() 方法将中断标志设为 true,表示 "我希望你停下来了",而是否停下来取决于程序员的代码逻辑,不一定会真的中断,只是希望中断!lambda 表达式中要判断是否被中断,有两种方式:Thread.interrupted()Thread.currentThread().isInterrupted(),更推荐这种方式,因为保持中断标志不变有助于上层逻辑知道这个线程是否被中断过。interrupt() 的是休眠或者阻塞的线程,则会抛出 InterruptedException 异常,此时捕获异常后,可以在异常中处理一些需要收尾的业务,而不要直接抛出 RuntimeException 等异常来终止进程,这样子是不合理的!如下面代码所示:public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
// 还没被打断则进行循环
while (Thread.currentThread().isInterrupted() == false) {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// 此时最好恢复中断标志,因为 sleep 抛出异常时会清除中断状态💥💥💥
Thread.currentThread().interrupt();
// 处理可能剩余的业务,而不至于直接退出导致业务完成一半
// ...
break;
}
}
});
t.start();
System.out.println("main thread, 3秒后中断子线程");
Thread.sleep(3000);
t.interrupt();
}3. 有时我们需要等待一个线程完成它的工作后,才能进行自己的下一步工作。例如,张三只有等李四转账成功,才能决定是否存钱,这时我们需要 join() 来明确等待线程的结束,在张三的线程中调用 李四.join() 即可保证在李四之后进行存钱操作!
4. JVM 只有在一个进程的所有非后台线程结束后,才会结束运行。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。