线程状态
1 线程停止
//测试停止线程
//1.建议线程正常停止 利用次数
//2.建议使用标志位
//3.不要使用过时或者不建议使用的方法
public class TestStop implements Runnable{
//(1)设置一个标志位
private boolean flag=true;
@Override
public void run() {
int i=0;
while(flag){
System.out.println("run"+ i++);
}
}
//(2)设置一个公开的方法停止线程
private void stop(){
this.flag=false;
}
public static void main(String[] args) {
TestStop testStop = new TestStop();
new Thread(testStop).start();
for(int i=0;i<20;i++){
System.out.println("main"+i);
if (i==15){
//调用stop方法切换标志位,让线程停止 跳出run
testStop.stop();
System.out.println("stop");
}
}
}
}
2 线程休眠
- 每个对象都要一把锁,Thread.sleep()不会释放琐
//模拟倒计时
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TreeMap;
public class TestSleep2{
public static 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) throws InterruptedException {
//打印当前系统时间
Date startTime = new Date(System.currentTimeMillis()); //获取系统当前时间
while (true){
System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));
Thread.sleep(1000);
startTime=new Date(System.currentTimeMillis()); //更新当前时间
}
}
}
3 线程礼让
Thread.yield()
- 让当前正在执行的线程暂停,但不阻塞
- 将线程从运行状态转换为就绪状态
- 让CPU重新调度,礼让不一定成功
//测试礼让线程
//礼让不一定成功,要看CPU调度
public class TestYield{
public static void main(String[] args) {
//创建Runnable接口实现对象
MyYield myYield = new MyYield();
// 两个线程
//创建线程对象,通过线程对象来开启线程 代理
new Thread(myYield,"a").start();
new Thread(myYield,"b").start();
}
}
class MyYield implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" begin");
Thread.yield(); //线程礼让 礼让不成功 直接开始停止 礼让成功 开始后让其他线程跑
System.out.println(Thread.currentThread().getName()+" end");
}
}
4 线程强制执行
Thread.join()
//测试join方法
public class TestJoin implements Runnable{
@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println("vip"+i);
}
}
public static void main(String[] args) throws InterruptedException {
//创建Runnable接口实现对象
TestJoin testJoin = new TestJoin();
//创建线程对象,通过线程对象来开启线程 代理
Thread thread = new Thread(testJoin); //thread代理testJoin
thread.start();
//
for (int i = 0; i < 100; i++) {
System.out.println("main"+i);
if (i==20){
thread.join(); //强制主线程暂停 让其他线程执行
}
}
}
}
5 线程状态观察
Thread.State
线程可以处于以下状态之一:
(1)NEW
尚未启动的线程处于此状态
(2)RUNNABLE
在java虚拟机中执行的线程处于此状态
(3)BOLCKED
被阻塞等待、监视器锁定的线程处于此状态
(4)WAITING
正在 等待另一个线程执行特定动作 的线程处于此状态
(5)TIMED_WAITING
正在 等待另一个线程执行动作 达到 指定等待时间 的线程处于此状态
(6)TERMINATED
已退出的线程处于此状态
-
监测线程状态
public class TestState{ public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(() -> { for (int i = 0; i < 5; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("//"); }); //状态观察 Thread.State state = thread.getState(); System.out.println(state); //还未调用start9() 所以state 为 NEW //观察启动后 thread.start(); //启动线程 state = thread.getState(); System.out.println(state); //调用start9() 所以state 为 RUNNABLE //当子线程重写的run方法执行完后,线程就停住了 while (state!=Thread.State.TERMINATED){ //只要线程不终止,就一直输出状态 Thread.sleep(100); state = thread.getState(); //更新线程状态 System.out.println(state); //调用start9() 所以state 为 Run } // thread.start();//线程停止之后就退出 无法调用start //线程只能启动一次 死亡之后的线程不能再启动 } } // @Override // public void run() { // for (int i = 0; i < 5; i++) { // try { // Thread.sleep(1000); // } catch (InterruptedException e) { // e.printStackTrace(); // } // System.out.println("//"); // } // 相当于 Lamda表达式 // () -> { // for (int i = 0; i < 5; i++) { // try { // Thread.sleep(1000); // } catch (InterruptedException e) { // e.printStackTrace(); // } // } // System.out.println("//"); // }
6 线程的优先级
-
java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,调度器按照优先级决定应该调度哪个线程执行
-
线程优先级用1~10数字表示
- Thread.MIN_PRIORITY=1;
- Thread.MAX_PRIORITY=10;
- Thread.NORM_PRIORITY=5;
-
使用 getPriority()和setPriority(int p) 获取和改变优先级
//测试线程的优先级
//优先级高的线程 大概率会先启动 不一定会最先启动
public class TestPriorty {
public static void main(String[] args) {
//主线程默认优先级
System.out.println(Thread.currentThread().getName()+":"+Thread.currentThread().getPriority());
MyPriorty myPriorty=new MyPriorty();
Thread t1=new Thread(myPriorty,"t1");
Thread t2=new Thread(myPriorty,"t2");
Thread t3=new Thread(myPriorty,"t3");
Thread t4=new Thread(myPriorty,"t4");
//先设置优先级再启动
t1.start();
t2.setPriority(1);
t2.start();
t3.setPriority(4);
t3.start();
t4.setPriority(10);
t4.start();
}
}
class MyPriorty implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+":"+Thread.currentThread().getPriority());
}
}
7 守护线程
- 线程分为用户线程和守护线程
- 虚拟机必须确保用户线程执行完毕
- 虚拟机不用等待守护线程执行完毕
- 例如:后台记录操作日志,监控内存,垃圾回收等
//测试守护线程
//上帝守护你
public class TestDaemon {
public static void main(String[] args) {
God god = new God();
Thread thread = new Thread(god); //代理
thread.setDaemon(true); //默认为false true为守护线程 不用等待守护线程执行完毕
thread.start();
You you = new You();
new Thread(you).start(); //用户线程停止
}
}
//my
class You implements Runnable{
@Override
public void run() {
for (int i = 0; i < 36500; i++) {
System.out.println("happy");
}
System.out.println("bye=================================");
}
}
//God
class God implements Runnable{
@Override
public void run() {
while (true){
System.out.println("bless");
}
}
}