一、五大状态
- 创建状态:new的时候,一旦创建就进入到该状态
- 就绪状态:调用
start()时,等待CPU调度,进入该状态 - 运行状态:CPU真正调用该线程的时候
- 阻塞状态:等待用户输入或者
sleep() - 死亡状态:线程中断或者结束,一旦进入死亡就不能再次启动
二、线程方法
2.1 线程停止
- 不推荐
JDK提供的stop()和destroy()方法(已废弃) - 推荐线程自己停止下来
- 建议使用一个标志位进行终止变量
/**
* @ClassName ThreadStop
* @Description
* 停止线程,建议线程自己停止,使用标志位
* 不要使用JDK中stop和destroy
* @Author wangwk-a
* @Date 2022/1/1 19:47
* @Version 1.0
*/
public class ThreadStop implements Runnable{
public static final int THREAD_LOOP = 50;
public static final int STOP_THREAD_TIMES = 30;
/**
* TODO: 1. 设置一个标志位
*/
private Boolean flag = true;
@Override
public void run() {
int i = 0;
while (flag) {
System.out.println(Thread.currentThread().getName() + "线程正在执行" + i++);
}
}
/**
* TODO: 2. 设置一个公开的方法停止线程
*/
public void stopThread() {
this.flag = false;
}
public static void main(String[] args) {
ThreadStop threadStop = new ThreadStop();
new Thread(threadStop).start();
for (int i = 0; i < THREAD_LOOP; i++) {
System.out.println(Thread.currentThread().getName() + "线程正在执行" + i);
if (i == STOP_THREAD_TIMES) {
threadStop.stopThread();
System.out.println("线程该停止了");
}
}
}
}
main线程正在执行0
main线程正在执行1
Thread-0线程正在执行0
Thread-0线程正在执行1
main线程正在执行2
Thread-0线程正在执行2
main线程正在执行3
main线程正在执行4
main线程正在执行5
Thread-0线程正在执行3
Thread-0线程正在执行4
Thread-0线程正在执行5
Thread-0线程正在执行6
Thread-0线程正在执行7
Thread-0线程正在执行8
Thread-0线程正在执行9
main线程正在执行6
main线程正在执行7
main线程正在执行8
main线程正在执行9
main线程正在执行10
main线程正在执行11
main线程正在执行12
main线程正在执行13
Thread-0线程正在执行10
main线程正在执行14
main线程正在执行15
main线程正在执行16
main线程正在执行17
Thread-0线程正在执行11
main线程正在执行18
Thread-0线程正在执行12
main线程正在执行19
main线程正在执行20
main线程正在执行21
main线程正在执行22
Thread-0线程正在执行13
Thread-0线程正在执行14
Thread-0线程正在执行15
Thread-0线程正在执行16
Thread-0线程正在执行17
Thread-0线程正在执行18
Thread-0线程正在执行19
Thread-0线程正在执行20
Thread-0线程正在执行21
Thread-0线程正在执行22
Thread-0线程正在执行23
Thread-0线程正在执行24
Thread-0线程正在执行25
Thread-0线程正在执行26
Thread-0线程正在执行27
Thread-0线程正在执行28
Thread-0线程正在执行29
main线程正在执行23
main线程正在执行24
main线程正在执行25
Thread-0线程正在执行30
Thread-0线程正在执行31
Thread-0线程正在执行32
main线程正在执行26
main线程正在执行27
main线程正在执行28
main线程正在执行29
main线程正在执行30
Thread-0线程正在执行33
线程该停止了
main线程正在执行31
main线程正在执行32
main线程正在执行33
main线程正在执行34
main线程正在执行35
main线程正在执行36
main线程正在执行37
main线程正在执行38
main线程正在执行39
main线程正在执行40
main线程正在执行41
main线程正在执行42
main线程正在执行43
main线程正在执行44
main线程正在执行45
main线程正在执行46
main线程正在执行47
main线程正在执行48
main线程正在执行49
Process finished with exit code 0
2.2 线程休眠Sleep
sleep(时间)指定当前线程阻塞的毫秒数sleep存在InterruptedExceptionsleep时间打倒后线程进入就绪状态sleep可以模拟网络延时,倒计时等- 每一个对象都有一个锁,
sleep不会释放锁
/**
* @ClassName ThreadSleep
* @Description 模拟倒计时
* @Author wangwk-a
* @Date 2022/1/1 20:05
* @Version 1.0
*/
public class ThreadSleep {
public void tenDown() throws InterruptedException {
int num = 10;
while (true) {
Thread.sleep(1000);
System.out.println(num--);
if (num <= 0) {
break;
}
}
}
public static void main(String[] args) {
ThreadSleep threadSleep = new ThreadSleep();
try {
threadSleep.tenDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
10
9
8
7
6
5
4
3
2
1
Process finished with exit code 0
2.3 线程礼让Yield
- 礼让线程,让当前正在执行的线程暂停,但不阻塞
- 将线程从运行状态转为就绪状态
- 让CPU重新调度,礼让不一定成功,看CPU状态
/**
* @ClassName ThreadYield
* @Description 测试礼让线程,礼让不一定成功
* @Author wangwk-a
* @Date 2022/1/1 20:14
* @Version 1.0
*/
public class ThreadYield {
public static void main(String[] args) {
MyYield myYield = new MyYield();
/**
* 如果礼让成功:
* a线程开始执行
* b线程开始执行
* b线程结束执行
*/
new Thread(myYield, "a").start();
new Thread(myYield, "b").start();
}
}
class MyYield implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "线程开始执行");
// 线程礼让
Thread.yield();
System.out.println(Thread.currentThread().getName() + "线程结束执行");
}
}
// 礼让成功
a线程开始执行
b线程开始执行
a线程结束执行
b线程结束执行
// 礼让不成功
a线程开始执行
a线程结束执行
b线程开始执行
b线程结束执行
2.4 线程合并Join
- Join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞
- 可以想想成插队
/**
* @ClassName threadJoin
* @Description 测试线程合并,想想为插队
* @Author wangwk-a
* @Date 2022/1/1 20:21
* @Version 1.0
*/
public class ThreadJoin implements Runnable{
public static final int THREAD_LOOP = 10;
public static final int MAIN_THREAD_LOOP = 30;
public static final int JOIN_TIMES = 5;
@Override
public void run() {
for (int i = 0; i < THREAD_LOOP; i++) {
System.out.println("线程VIP来了--" + i);
}
}
public static void main(String[] args) throws InterruptedException {
ThreadJoin threadJoin = new ThreadJoin();
Thread thread = new Thread(threadJoin);
for (int i = 0; i < MAIN_THREAD_LOOP; i++) {
if (i == JOIN_TIMES) {
// 插队
thread.start();
thread.join();
}
System.out.println("Main--" + i);
}
}
}
Main--0
Main--1
Main--2
Main--3
Main--4
线程VIP来了--0
线程VIP来了--1
线程VIP来了--2
线程VIP来了--3
线程VIP来了--4
线程VIP来了--5
线程VIP来了--6
线程VIP来了--7
线程VIP来了--8
线程VIP来了--9
Main--5
Main--6
Main--7
Main--8
Main--9
Main--10
Main--11
Main--12
Main--13
Main--14
Main--15
Main--16
Main--17
Main--18
Main--19
Main--20
Main--21
Main--22
Main--23
Main--24
Main--25
Main--26
Main--27
Main--28
Main--29
Process finished with exit code 0
三、线程状态观测
**Thread.State**可以处于一下状态之一:
NEW:尚未启动的线程处于此状态RUNNABLE:在Java虚拟机中执行的线程处于此状态BLOCKED:被阻塞等待监视器锁定的线程处于此状态WAITTING:正在等待另一个线程执行特定动作的线程处于此状态TIMED WAITTING:正在等待另一个线程执行动作达到指定等待时间的线程处于此状态TERMINATED:已退出的线程处于此状态
一个线程可以在给定时间点处于一个状态,这些状态时不反应任何操作系统线程状态的虚拟机状态。
/**
* @ClassName ThreadStatus
* @Description 观测线程状态
* @Author wangwk-a
* @Date 2022/1/1 20:36
* @Version 1.0
*/
public class ThreadStatus {
public static final int THREAD_LOOP = 1;
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(()->{
for (int i = 0; i < THREAD_LOOP; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("//////");
});
// NEW
Thread.State stateNew = thread.getState();
System.out.println(stateNew);
// RUNNABLE
thread.start();
Thread.State stateRunnable = thread.getState();
System.out.println(stateRunnable);
// 只要线程不终止,就一直输出状态
while (stateRunnable != Thread.State.TERMINATED) {
Thread.sleep(100);
// 更新线程状态
stateRunnable = thread.getState();
System.out.println(stateRunnable);
}
}
}
NEW
RUNNABLE
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
//////
TERMINATED
四、线程优先级
- Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行
- 线程优先级用数字表示,范围从1~10
Thread.MIN_PRIORITY = 1;Thread.MAX_PRIORITY = 10;Thread.MORM_PRIORITY = 5;
- 使用以下方式改变或获取线程优先级
getPriority()setPriority(int xxx)
/**
* @ClassName ThreadPriorityTest
* @Description 测试线程优先级
* @Author wangwk-a
* @Date 2022/1/1 20:49
* @Version 1.0
*/
public class ThreadPriorityTest {
public static void main(String[] args) {
System.out.println("Main -->" + Thread.currentThread().getPriority());
MyPriority myPriority = new MyPriority();
Thread thread1 = new Thread(myPriority);
Thread thread2 = new Thread(myPriority);
Thread thread3 = new Thread(myPriority);
Thread thread4 = new Thread(myPriority);
// 先设置优先级
thread1.start();
thread2.setPriority(1);
thread2.start();
thread3.setPriority(4);
thread3.start();
thread4.setPriority(Thread.MAX_PRIORITY);
thread4.start();
}
}
class MyPriority implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "-->" + Thread.currentThread().getPriority());
}
}
Main -->5
Thread-0-->5
Thread-1-->1
Thread-3-->10
Thread-2-->4
Process finished with exit code 0
优先级低只是意味着获得调度的概率低,并不是优先级低就不会被调用,这都看CPU的调度
五、守护线程Daemon
- 线程分为用户线程和守护线程
JVM必须确保用户线程执行完毕JVM不必等待守护线程执行完毕- 守护线程一般后台记录操作日志、监控内存、垃圾回收等
/**
* @ClassName DaemonTEst
* @Description 测试守护线程
* @Author wangwk-a
* @Date 2022/1/1 21:13
* @Version 1.0
*/
public class DaemonTest {
public static void main(String[] args) {
God god = new God();
You you = new You();
Thread daemonThread = new Thread(god);
// 设置为守护线程
daemonThread.setDaemon(true);
daemonThread.start();
new Thread(you).start();
}
}
class God implements Runnable {
@Override
public void run() {
while (true) {
System.out.println("上帝保佑你");
}
}
}
class You implements Runnable {
public static final int THREAD_LOOP = 30;
@Override
public void run() {
for (int i = 0; i < THREAD_LOOP; i++) {
System.out.println("你开心的活着");
}
System.out.println("=======GoodBye World=======");
}
}
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
=======GoodBye World=======
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
Process finished with exit code 0