多线程状态
方法 | 说明 |
setPriority(int newPriority) | 更改线程的优先级 |
static void sleep(long millis) | 在指定的毫秒数内让当前正在执行的线程休眠 |
void join() | 等待该线程终止 |
static void yield() | 暂停当前正在执行的线程对象,并执行其他线程 |
void stop() | 线程中断,已被弃用,因为它是直接中断,相当于直接给你停电,这种方式太暴力,不安全 |
void interrupt() | 中断线程,非直接中断,而是将当前线程标志为中断标记,只是一个标记 |
boolean isAlive() | 测试线程是否处于活动状态 |
停止线程:
- 不推荐使用JDK提供的stop()、destroy()方法。【已弃用】
- 推荐线程自己停止下来
- 建议使用一个标志位进行终止变量,当flag=false时,则终止线程运行。
线程停止 实例代码:
1 package com.huolongluo.coindemo.morethread.sub2; 2 3 /** 4 * Created by 火龙裸 on 2019/11/9. 5 * desc : 测试stop 6 * 1.建议线程正常停止--->利用次数,不建议死循环 7 * 2.建议使用标志位--->设置一个标志位 8 * 3.不要使用stop或者destroy等过时或者JDK不建议使用的方法 9 * version: 1.0 10 */ 11 public class TestStop implements Runnable { 12 13 //1.设置一个标志位 14 private boolean flag = true; 15 16 @Override 17 public void run() { 18 int i = 0; 19 while (flag) { 20 System.out.println("run.....Thread" + (i++)); 21 } 22 } 23 24 //2.设置一个公开的方法停止线程,转换标志位 25 public void stopThread() { 26 this.flag = false; 27 } 28 29 public static void main(String[] args) { 30 TestStop testStop = new TestStop(); 31 new Thread(testStop).start(); 32 33 for (int i = 0; i < 1000; i++) { 34 System.out.println("main " + i); 35 if (i == 900) { 36 //调用stopThread方法改变标志位状态,让线程停止 37 testStop.stopThread(); 38 System.out.println("线程该停止了"); 39 } 40 } 41 } 42 }
这段实现,当主线程的i走到900的时候,也就是当打印到“main 900”之后,会打印“线程该停止了”,这个时候,子线程就不会再打印出来“run.....Thread”了。
线程休眠:
- sleep(时间)指定当前线程阻塞的毫秒数;
- sleep存在异常InterruptedException;
- sleep时间达到后线程进入就绪状态;
- sleep可以模拟网络延时,倒计时等;
- 每个对象都有一个锁,sleep不会释放锁;
线程休眠 实例代码:
1 package com.huolongluo.coindemo.morethread.sub2; 2 3 /** 4 * Created by 火龙裸 on 2019/11/9. 5 * desc : 模拟网络延时:方法问题的发生性(多个线程同时操作同一个资源对象时,是线程不安全的) 6 * version: 1.0 7 */ 8 public class TestSleep implements Runnable { 9 //票数 10 private int ticketNums = 10; 11 12 @Override 13 public void run() { 14 while (true) { 15 if (ticketNums <= 0) { 16 break; 17 } 18 //模拟延时 19 try { 20 Thread.sleep(100); 21 } catch (InterruptedException e) { 22 e.printStackTrace(); 23 } 24 System.out.println(Thread.currentThread().getName() + " 拿到了第:" + ticketNums-- + " 张票"); 25 } 26 } 27 28 public static void main(String[] args) { 29 30 TestSleep testSleep = new TestSleep(); 31 32 new Thread(testSleep, "小明").start(); 33 new Thread(testSleep, "老师").start(); 34 new Thread(testSleep, "黄牛党").start(); 35 } 36 }
运行结果:
出现-1张票,所以多个线程同时操作同一个资源对象,是不安全的。
线程礼让:
- 礼让线程,让当前正在执行的线程暂停,但不阻塞
- 将线程从运行状态转为就绪状态
- 让CPU重新调度,礼让不一定成功!看CPU心情
线程礼让 实例代码:
1 package com.huolongluo.coindemo.morethread.sub2; 2 3 /** 4 * Created by 火龙裸 on 2019/11/9. 5 * desc : 测试礼让线程 6 * <p> 7 * 礼让不一定成功,看CPU心情 8 * version: 1.0 9 */ 10 public class TestYield { 11 public static void main(String[] args) { 12 MyYield myYield = new MyYield(); 13 new Thread(myYield, "a").start(); 14 new Thread(myYield, "b").start(); 15 } 16 } 17 18 class MyYield implements Runnable { 19 @Override 20 public void run() { 21 System.out.println(Thread.currentThread().getName() + "线程开始执行"); 22 Thread.yield();//礼让 23 System.out.println(Thread.currentThread().getName() + "线程停止执行"); 24 } 25 }
运行结果:
所以礼让,有可能成功,有可能不成功。
合并线程:
- Join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞。
- 可以想象成插队。
- 会让线程阻塞,尽量少用
线程合并 实例代码:
1 package com.huolongluo.coindemo.morethread.sub2; 2 3 /** 4 * Created by 火龙裸 on 2019/11/9. 5 * desc : 测试Join方法,想象成插队,非常霸道 6 * version: 1.0 7 */ 8 public class TestJoin implements Runnable { 9 @Override 10 public void run() { 11 for (int i = 0; i < 100; i++) { 12 System.out.println("线程Vip来了" + i); 13 } 14 } 15 16 public static void main(String[] args) throws InterruptedException { 17 //启动我们的线程 18 TestJoin testJoin = new TestJoin(); 19 Thread thread = new Thread(testJoin); 20 thread.start(); 21 22 //主线程 23 for (int i = 0; i < 1000; i++) { 24 if (i == 200) { 25 thread.join();//插队(这里一插队,就是当主线程执行到i==200的时候,就让子线程去执行打印“线程Vip来了”,必须等插队的那个子线程打印100条“线程Vip”执行完了,再继续执行主线程没有执行完的语句。) 26 } 27 System.out.println("main" + i); 28 } 29 } 30 }
线程状态观测:
- Thread.State
线程状态。线程可以处于以下状态之一:
- NEW 尚未启动的线程处于此状态
- RUNNABLE 在Java虚拟机中执行的线程处于此状态
- BLOCKED 被阻塞等待监视器锁定的线程处于此状态
- WAITING 正在等待另一个线程执行特定动作的线程处于此状态
- TIMED_WAITING 正在等待另一个线程执行动作达到指定等待时间的线程处于此状态
- TERMINATED 已退出的线程处于此状态
一个线程可以在给定的时间点处于一个状态。这些状态是不反应任何操作系统线程状态的虚拟机状态。
线程状态观测 实例代码:
1 package com.huolongluo.coindemo.morethread.sub2; 2 3 /** 4 * Created by 火龙裸 on 2019/11/9. 5 * desc : 观察测试线程的状态 6 * version: 1.0 7 */ 8 public class TestState { 9 public static void main(String[] args) throws InterruptedException { 10 Thread thread = new Thread(new Runnable() { 11 @Override 12 public void run() { 13 for (int i = 0; i < 5; i++) { 14 try { 15 Thread.sleep(100); 16 } catch (InterruptedException e) { 17 e.printStackTrace(); 18 } 19 } 20 System.out.println("///////"); 21 } 22 }); 23 24 //观察状态 25 Thread.State state = thread.getState(); 26 System.out.println(state);//NEW 27 28 //观察启动后 29 thread.start(); 30 state = thread.getState(); 31 System.out.println(state);//Run 32 33 while (state != Thread.State.TERMINATED) {//只要线程不终止,就一直输出 34 Thread.sleep(100); 35 state = thread.getState();//更新线程状态 36 System.out.println(state);//输出状态 37 } 38 } 39 }
运行结果:
需要注意的是,死亡之后的线程是不能再次启动,否则会报错。
线程优先级:
- Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行。
- 线程的优先级用数字表示,范围从1~10.
Thread.MIN_PRIORITY=1;
Thread.MAX_PRIORITY=10;
Thread.NORM_PRIORITY=5;
- 使用一下方式改变或获取优先级
getPriority(); setPriority(int xxx)
线程优先级 实例代码:
1 package com.huolongluo.coindemo.morethread.sub2; 2 3 /** 4 * Created by 火龙裸 on 2019/11/9. 5 * desc : 测试线程的优先级 6 * version: 1.0 7 */ 8 public class TestPriority extends Thread { 9 public static void main(String[] args) { 10 //主线程 默认优先级 为5 11 System.out.println(Thread.currentThread().getName() + "--->" + Thread.currentThread().getPriority()); 12 13 MyPriority myPriority = new MyPriority(); 14 15 Thread thread1 = new Thread(myPriority); 16 Thread thread2 = new Thread(myPriority); 17 Thread thread3 = new Thread(myPriority); 18 19 //先设置优先级,再启动,不设置优先级,默认为5 20 thread1.start(); 21 22 thread2.setPriority(3); 23 thread2.start(); 24 25 thread3.setPriority(Thread.MAX_PRIORITY);//MAX_PRIORITY = 10 26 thread3.start(); 27 } 28 } 29 30 class MyPriority implements Runnable { 31 32 @Override 33 public void run() { 34 System.out.println(Thread.currentThread().getName() + "--->" + Thread.currentThread().getPriority()); 35 } 36 }
运行结果:
可以看到,设置优先级,但却不一定说优先级高的就一定能先执行。因为优先级低的线程,只是说它被CPU调度的概率低,并不是说优先级低就不会被调度到,这个决定权还是得看CPU。
守护线程(daemon):
- 线程分为用户线程和守护线程
- 虚拟机必须确保用户线程执行完毕
- 虚拟机不用等待守护线程执行完毕
- 如:后台记录操作日志,监控内存,垃圾回收等待..
可以通过setDaemon(true)把线程设置成守护线程, 默认是false,表示用户线程,正常的线程都是用户线程。
守护线程 实例代码:
1 package com.huolongluo.coindemo.morethread.sub2; 2 3 /** 4 * Created by 火龙裸 on 2019/11/9. 5 * desc : 测试守护线程 6 * <p> 7 * 上帝守护你 8 * version: 1.0 9 */ 10 public class TestDaemon { 11 public static void main(String[] args) { 12 God god = new God(); 13 You you = new You(); 14 15 Thread thread = new Thread(god); 16 thread.setDaemon(true);//默认是false,表示用户线程,正常的线程都是用户线程 17 thread.start();//上帝 守护线程启动... 18 19 new Thread(you).start();//你 用户线程启动... 20 } 21 } 22 23 //上帝 24 class God implements Runnable { 25 26 @Override 27 public void run() { 28 while (true) {//因为虚拟机不用等待守护线程执行完毕,所以这里直接给了一个true条件 29 System.out.println("上帝保佑着你"); 30 } 31 } 32 } 33 34 //你 35 class You implements Runnable { 36 37 @Override 38 public void run() { 39 for (int i = 0; i < 36500; i++) { 40 System.out.println("你一生都开心地或者"); 41 } 42 System.out.println("=======goodbye! world!======");//hello ,world 43 } 44 }
程序只要当用户线程执行完毕后,就会停止,程序不会根据守护线程是否执行完毕,而是根据用户线程,用户线程执行完了,程序也就结束了。