一.线程创建
方法1:继承Thread类
继承Thread来创建一个线程类,重写run()方法
class MyThread extends Thread{
@Override
public void run() {
// super.run();
System.out.println("MyThread run");
}
}
public class Demo18 {
public static void main(String[] args) {
MyThread t=new MyThread();
t.start();
System.out.println("main run");
}
}
执行结果如下:

方法2:实现Runnable接口
1.实现Runnable接口
- 创建一个类并实现
java.lang.Runnable接口 - 必须实现
run()方法,在其中编写线程要执行的业务逻辑
class MyRunnable implements Runnable {
@Override
public void run() {
// 线程执行的具体任务
for(int i=0; i<5; i++){
System.out.println("线程运行中: "+i);
}
}
}
2.创建Thread实例
- 实例化实现Runnable接口的类对象
- 通过Thread类的构造方法创建线程对象
-
MyRunnable myRunnable = new MyRunnable(); Thread thread = new Thread(myRunnable); // 或者带线程名称 Thread namedThread = new Thread(myRunnable, "MyThread-1");
3.调用start方法
- 调用Thread实例的
start()方法启动线程
class MyThread implements Runnable{
@Override
public void run() {
System.out.println("MyThread run");
}
}
public class Demo19 {
public static void main(String[] args) {
MyThread myRunnable = new MyThread();
Thread t = new Thread(myRunnable);
t.start();
System.out.println("main run");
}
}
方法3:匿名内部类创建Thread子类对象
public static void main(String[] args) {
Thread t=new Thread(){
@Override
public void run() {
System.out.println("MyThread run");
}
};
}
方法4:匿名内部类创建Runnable子类对象
public static void main(String[] args) {
Thread t=new Thread(new Runnable() {
@Override
public void run() {
System.out.println("MyThread run");
}
});
}
方法5:lambda表达式创建Runnable子类对象(最常用)
public static void main(String[] args) {
Thread t=new Thread(()->{
System.out.println("MyThread run");
});
t.start();
}
二.Thread常见的方法
1.常见的构造方法
| Thread() | 创建线程对象 |
| Thread(Runnable target) | 使用Runnable对象创建线程 |
| Thread(Runnable target,String name) | 使用Runnable对象创建线程并给创建的线程命名 |
2.常见的属性
| ID | getId() |
| 名称 | getName() |
| 状态 | getState() |
| 优先级 | getDaemon() |
| 是否是后台线程 | isDaemon() |
| 是否存活 | isAlive() |
- ID是线程的唯一标识,不同线程不会重复
- 名称是各种调试工具用到的
- 状态表示线程当前所处的一个情况
- 优先级高的线程更容易被调度到
- 后台线程:负责维持进程的正常运行,但其生命周期不会直接影响进程的终止。即使后台线程仍在执行,进程仍可正常退出。
- 前台线程:作为进程终止的关键因素,其执行状态直接影响进程的生命周期。若存在多个前台线程,进程必须等待所有前台线程执行完毕才会结束。
- 是否存活,可以理解为run()方法运行完就结束了
3.启动线程-start()
- 调用start动作非常快
一旦执行start,代码会立刻向下执行,不会产生任何阻塞。
- 一个对象的start方法只能执行一次
start和run的区别:
start()方法是线程类的核心方法,调用后会触发以下行为:
- 创建一个新的操作系统级线程,由 JVM 和操作系统共同调度。
- 在新创建的线程中自动调用
run()方法,实现异步执行。
run()方法仅仅是线程类的普通方法:
- 直接调用
run()不会创建新线程,代码仍在当前线程中同步执行。- 其逻辑与普通方法调用无异,无法实现多线程并发效果。
三.线程的中断
线程的中断可以理解为打断这个线程,线程打断有两种方法。
方法一:用标志位
public class Demo24 {
public static boolean flag=true;
public static void main(String[] args) {
Thread t=new Thread(()->{
while(flag){
try {
System.out.println("MyThread run");
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
t.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
flag=false;
}
}
方法二:使用thread对象的interrupt()方法通知线程结束
public static void main(String[] args) {
Thread t=new Thread(()->{
while(!Thread.currentThread().isInterrupted()){
try {
Thread.sleep(1000);
System.out.println("MyThread run");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
// break;
}
}
});
t.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
t.interrupt();
System.out.println("MyThread interrupt");
}
注意:
当一个线程处于
sleep状态时,若其他线程调用该线程的interrupt()方法,会触发以下行为:
sleep状态的线程会被立即唤醒,并抛出InterruptedException异常。- 线程的
isInterrupted标志会被自动重置为false,这是Java中断机制的设计特性。
线程中断与sleep的交互机制
调用 interrupt() 方法会中断处于 sleep 状态的线程,触发 InterruptedException 异常。该异常的处理逻辑会清除线程的中断标志位(即 isInterrupted 返回 false)
恢复中断标志的方法
在catch块中加break(推荐),这种方式让线程决定自己是否要终止。
public static void main(String[] args) {
Thread t=new Thread(()->{
while(!Thread.currentThread().isInterrupted()){
try {
Thread.sleep(1000);
System.out.println("MyThread run");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
// e.printStackTrace();
break;
}
}
});
t.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
t.interrupt();
System.out.println("MyThread interrupt");
}
线程中断的总结:
使用Interrupt方法的时候,
1.如果线程没有进行sleep等阻塞操作,线程的isInterrupted()方法返回true,可以通过循环条件结束线程。
2.如果线程进行sleep等阻塞操作,线程的isInterrupted()返回的是true,但是sleep如果被提前唤醒,抛出InterruptException异常,同时会把isInterrupted()的返回结果设置为false,此时就需要手动决定是否要结束线程了。
四.等待线程
有的时候,我们需要等待一个线程完成它的工作后,才能进行下一步工作。
示例一:
public static void main(String[] args) {
Thread t=new Thread(()->{
for(int i=0;i<10;i++){
System.out.println("MyThread run"+i);
}
});
t.start();
try {
t.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("MyThread join");
}

示例二:
public static void main(String[] args) throws InterruptedException {
Runnable target=()->{
for(int i=0;i<10;i++){
try {
System.out.println(Thread.currentThread().getName()+":我还在找工作");
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// System.out.println("MyThread run"+i);
}
};
Thread thread1=new Thread(target,"李四");
Thread thread2=new Thread(target,"王五");
System.out.println("先让李四开始找工作");
thread1.start();
thread1.join();
System.out.println("李四工作结束了,让王五开始找工作");
thread2.start();
thread2.join();
System.out.println("王五工作结束了");
}
如果把join去掉会出现:

注意:哪个线程调用join,哪个线程就是"等待的一方"
| public void join() | 等待线程结束 |
| public void join(long millis) | 等待线程结束,最多等待millis毫秒 |
| public void join(long millis,int nanos) | 同理,但可以更高的精度 |
五.获取当前线程引用
| public static Thread currentThread(); | 返回当前线程对象的引用 |
public static void main(String[] args) {
Thread thread=Thread.currentThread();
System.out.println(thread);
System.out.println(thread.getName());
}
运行结果:

六.休眠当前进程
通过Thread.sleep()控制进程休眠:
Thread.sleep()本质就是让线程的状态变成"阻塞"状态,此时线程就不参与cpu调度了。直到时间到,这个线程状态恢复成"就绪"状态才能参与cpu调度

2003

被折叠的 条评论
为什么被折叠?



