多线程(二) ~ 线程核心属性与状态

文章目录

一. 线程创建(start)

(一)继承Thread类,重写run

java 复制代码
class MyThread extends Thread {
    @Override
    public void run() {
        while (true) {
            System.out.println("Thread!!!");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

public class demo1 {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new MyThread();
        thread.start();
        while (true) {
            System.out.println("main!!!");
            Thread.sleep(100);
        }

    }
}

(二)继承Runnable类,重写run

java 复制代码
class MyRunnable implements Runnable {
    @Override
    public void run() {
        while (true) {
            System.out.println("Thread!");
        }
    }
}


public class demo2 {
    public static void main(String[] args) {
        MyRunnable runnable = new MyRunnable();
        Thread thread = new Thread(runnable);
        thread.start();

        while (true) {
            System.out.println("main!");
        }
    }
}

(三)Thread匿名内部类重写

java 复制代码
package demo_thread;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 32309
 * Date: 2025-07-11
 * Time: 20:06
 */
public class demo3 {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread() {
            @Override
            public void run() {
                while (true) {
                    System.out.println("Thread~~");
                    try {
                        Thread.sleep(0);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }

                }
            }
        };
        thread.start();

        while (true) {
            System.out.println("main~~");
            Thread.sleep(0);
        }
    }
}

(四)Runnable匿名内部类重写

java 复制代码
package demo_thread;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 32309
 * Date: 2025-07-11
 * Time: 20:14
 */
public class demo4 {
    public static void main(String[] args) throws InterruptedException {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                while (true) {
                    System.out.println("thread~");
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        Thread thread = new Thread(runnable);
        thread.start();
        while (true) {
            System.out.println("main~");
            Thread.sleep(100);
        }
    }
}

(五)lambda表达式

java 复制代码
public class demo5 {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (true) {
                System.out.println("thread!");
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        },"阿然");
        thread.start();

        while (true) {
            System.out.println("main!");
            Thread.sleep(10);
        }
    }
}

二. 线程的关键属性

(一)线程名称

线程名字,我们可以通过setName方法来设置线程的名字,方便后期调试

通过getName方法可以获取线程名称

(二)线程是否为后台线程

1. 前台线程

当前台线程还在运行时,即使其他所有线程都运行完,进程也不停止,要等待前台线程结束,进程才结束

2. 后台线程

当所有前台线程运行完毕时,即使后台线程还有任务没有完成,也会终止进程

3. 查看是否是后台线程(isDaemon)

是否是后台线程通过isDeamon 方法来查看
Java中线程创建时默认是前台线程

4. 设置后台线程(setDaemon)代码及效果图

java 复制代码
public class demo7 {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (true) {
                System.out.println("thread~~~");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }

        },"thread");
        thread.setDaemon(true);
        thread.start();
        System.out.println(thread.isDaemon());

        for (int i = 0; i < 1   ; i++) {
            System.out.println("main");
            Thread.sleep(1000);
        }
    }
}

(三)线程是否存活

1. 是否存活isAlive

Java中Thread对象与CPU内核中的线程是一一对应的 ,但是有可能出现内核的线程已经摧毁了,而Thread对象还存在的情况

可以使用isAlive方法来查看线程是否存活

2. 代码及效果图

java 复制代码
package demo_thread;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 32309
 * Date: 2025-07-11
 * Time: 20:38
 */
public class demo8 {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 3; i++) {
                System.out.println("thread!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        thread.start();

        while (true) {
            System.out.println(thread.isAlive());
            Thread.sleep(1000);
        }

    }
}

三. 线程终止(interrupt)

(一)Java提供的API

1. 用法

1.Java中提供了控制线程结束的方法interrupted与isInterrupted

  1. isInterrupted默认是false,在循环中取反使用来运行线程任务

  2. 调用interrupt让isInterrupted置为true

  3. 需要注意的是sleep休眠函数会使isInterrupted再次置为false

2. 代码及效果图

java 复制代码
package demo_thread;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 32309
 * Date: 2025-07-11
 * Time: 20:52
 */
public class demo10_interrupt {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println(Thread.currentThread().getName());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    //throw new RuntimeException(e);
                    break;
                }
            }
            System.out.println("进程结束");
        },"thread");
        thread.start();
        Thread.sleep(3000);
        System.out.println("main尝试终止");
        thread.interrupt();

    }
}

(二)手动设置条件

1. 用法

复制代码
1. 手动设置循环关闭条件时,布尔条件需要是成员变量
2. 如果是局部变量那么布尔条件则不能改变,这样达不到关闭循环从而关闭线程的效果
3. 这是因为每次线程调度切换回该线程时,会从重新栈当中调取变量,如果局部变量则存在销毁可能,无法调取

2. 代码及其效果图

java 复制代码
package demo_thread;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 32309
 * Date: 2025-07-11
 * Time: 20:47
 */
public class demo9 {
    private static boolean isFinish = false;

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (!isFinish) {
                System.out.println("thread~~~");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.println("进程结束");
        },"thread");
        thread.start();

        for (int i = 0; i < 3; i++) {
            Thread.sleep(1000);
        }
        System.out.println("尝试终止进程翁");
        isFinish = true;

    }
}

四. 线程等待(join)

(一)定义

1.Java中线程等待函数时join

  1. 线程1调用join,线程1就是被等待的线程,要等到线程1结束后才能结束进程

  2. join可以设置等待时间,在设定的等待时间结束后,不论线程1是否完成任务,都不再等待,结束进程

  3. join会抛出一个InterruptedException异常

(二)代码及其效果图

java 复制代码
package demo_thread;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 32309
 * Date: 2025-07-12
 * Time: 20:08
 */
public class demo11_join {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 3; i++) {
                System.out.println("thread ~");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.println("thread 线程结束!");
        });

        thread.start();
        thread.join(4000);
        System.out.println("main 线程结束!");
    }
}

五. 获取线程引用(currentThread)

(一)用法

  1. Java中Thread封装了获取当前线程的API,即currentThread方法
  2. currentThread方法是静态方法,可以直接用类名Thread调用

(二)代码及其效果图

java 复制代码
package demo_thread;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 32309
 * Date: 2025-07-13
 * Time: 21:46
 */
public class demo_currentThread {
    public static void main(String[] args) {
        Thread main = Thread.currentThread();
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 3; i++) {
                System.out.println("thread@");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.println("thread 线程结束");
        });
        thread.start();

        for (int i = 0; i < 5; i++) {
            System.out.println("main@");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        System.out.println("main 结束");
    }
}

六. 线程休眠(sleep)

(一)定义

1 Java中休眠方法是sleep

  1. sleep方法是静态方法,可以直接用Thread调用

  2. 调用sleep方法会抛出InterruptedException异常

(二)代码

java 复制代码
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

七. 线程状态

(一)NEW

1. 定义

线程还未创建的状态,没调用start

2. 代码及其效果图

java 复制代码
package demo_thread;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 32309
 * Date: 2025-07-12
 * Time: 20:18
 */
public class demo12_new {
    public static void main(String[] args) {
        Thread thread = new Thread();

        System.out.println(thread.getState());
    }
}

(二)TERMINATED

1. 定义

线程终止状态,运行完毕已经结束

2. 代码及其效果图

java 复制代码
package demo_thread;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 32309
 * Date: 2025-07-12
 * Time: 20:21
 */
public class demo13_TERMINATED {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 3; i++) {

            }
        });
        thread.start();
        while (true) {
            System.out.println(thread.getState());
            Thread.sleep(1000);
        }
    }
}

(三)RUNNABLE

1. 定义

线程正在运行时状态

2. 代码及其效果图

java 复制代码
package demo_thread;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 32309
 * Date: 2025-07-12
 * Time: 20:28
 */
public class demo14_RUNNABLE {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            while (true) {
                
            }
        });
        thread.start();
        System.out.println(thread.getState());
    }
}

(四)TIMED_WAITING

1. 定义

有时间限制的等待的线程状态

2. 代码及其效果图

java 复制代码
package demo_thread;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 32309
 * Date: 2025-07-12
 * Time: 20:34
 */
public class demo15_TINE_WAITING {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (true) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        thread.start();
        thread.join(1000*10000);
    }
}

(五)WAITING

1. 定义

没有时间限制的等待的线程状态

2. 代码及其效果图

java 复制代码
package demo_thread;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 32309
 * Date: 2025-07-12
 * Time: 20:39
 */
public class demo16_WAITING {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (true) {

            }
        });

        thread.start();
        thread.join();

    }
}

(六)BLOCKED&LOCK

阻塞,这里我们只讨论的是加锁后阻塞,提到锁,不得不谈到死锁,有三种情况:

①:一个线程同时加锁两次

②:两个线程两把锁,一个线程获取到一把锁之后,再尝试获取另一把锁 时,加锁形成循环 ,那么就会形成死锁!

③:N个线程M把锁,每个线程运转都需要用到两把锁的时候,就会形成循环,造成死锁阻塞

(①)

观察下方实例,我们可以发现,用 synchronized 的时候对一个线程多次加锁,不会触发阻塞,这说明 synchronized 是可重入锁!

java 复制代码
package test;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: ran
 * Date: 2025-07-31
 * Time: 9:53
 * 一个线程多次加锁
 */
public class test1 {
    public static void main(String[] args) {
        Object lock = new Object();
        Thread thread1 = new Thread(() ->{
            synchronized (lock) {
                synchronized (lock) {
                    System.out.println("多次加锁!!!");
                }
            }   
        });
        thread1.start();
    }
}

(②)

观察下面的实例可以看出,线程1lock1 加锁后休眠1s, 再尝试对第二个 lock2 加锁时,会产生阻塞, 这是因为 线程2 已经对 lock2 加锁成功, 又尝试获取 lock1 的时候产生了阻塞, 导致 lock2 没有解锁, 所以 线程1 尝试获取 lock2 失败, 产生阻塞, 相互循环, 形成死锁

java 复制代码
package test;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: ran
 * Date: 2025-07-31
 * Time: 10:26
 */
public class test2 {
    public static void main(String[] args) {
        Object lock1 = new Object();
        Object lock2 = new Object();
        Thread thread1 = new Thread(() -> {
            synchronized (lock1) {
                System.out.println("获取第一把锁: lock1");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                synchronized (lock2) {
                    System.out.println("尝试获取第二把锁: lock2");
                }
            }
        });

        Thread thread2 = new Thread(() -> {
            synchronized (lock2) {
                System.out.println("获取第一把锁: lock2");
                synchronized (lock1) {
                    System.out.println("尝试获取第二把锁: lock1");
                }
            }
        });
        thread1.start();
        thread2.start();
    }
}

(③)

通过下方实例,我们可以看出, N个对象M把锁, 当每个人都要嵌套两把锁才能工作时,就会形成阻塞

java 复制代码
package test;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: ran
 * Date: 2025-07-31
 * Time: 10:54
 */
public class test3 {
    public static void main(String[] args) {
        Object lock1 = new Object();
        Object lock2 = new Object();
        Object lock3 = new Object();
        Thread thread1 = new Thread(() -> {
            synchronized (lock1) {
                System.out.println("获取第一把锁: lock1");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                synchronized (lock2) {
                    System.out.println("尝试获取第二把锁: lock2");
                }
            }
        });

        Thread thread2 = new Thread(() -> {
            synchronized (lock2) {
                System.out.println("获取第一把锁: lock2");
                synchronized (lock3) {
                    System.out.println("尝试获取第二把锁: lock3");
                }
            }
        });

        Thread thread3 = new Thread(() -> {
            synchronized (lock3) {
                System.out.println("获取第一把锁: lock3");
                synchronized (lock1) {
                    System.out.println("尝试获取第二把锁: lock1");
                }
            }
        });
        thread1.start();
        thread2.start();
        thread3.start();
    }
}