Java多线程:线程状态

线程状态

  • 创建状态
  • 就绪状态
  • 运行状态
  • 阻塞状态
  • 死亡状态,一旦结束无法再启动

线程状态关系图

线程方法

线程停止

  • 不推荐使用JDK提供的stop()destory()方法停止线程,推荐线程自己停止下来
  • 建议使用一个标志位进行中止变量,当flag = false,中止线程运行
  • 建议线程正常停止,利用次数,不进行死循环
public class TestStop implements Runnable{
    //设置标志位
    private boolean flag = true;

    @Override
    public void run() {
        int i = 0;
        while (flag){
            System.out.println("run" + i++);
        }
    }

    //设置公开方法停止线程,转换标志位
    public void stop(){
        this.flag = false;
    }

    public static void main(String[] args) {
        TestStop testStop = new TestStop();
        new Thread(testStop).start();

        for (int i = 0; i < 200; i++) {
            System.out.println("main" + i);//计时
            if (i == 99){
                testStop.stop();
                System.out.println("stop");
                break;
            }
        }
    }
}

线程休眠sleep

  • sleep(时长):指定当前线程阻塞的毫秒数
  • sleep存在异常InterruptedException
  • sleep时间达到后线程进入就绪状态
  • sleep可以模拟网络延时,倒计时等(放大问题的发生性)
  • 每一个对象都有一个锁,sleep不会释放锁

倒计时

public static void tenDown() throws InterruptedException {
    int num = 10;
    while (true){
        System.out.println(num--);
        Thread.sleep(1000);
        if (num < 0){
            break;
        }
    }
}

显示当前时间

public static void main(String[] args) {
    //打印当前时间
    Date startTime = new Date(System.currentTimeMillis());

    while(true){
        try {
            System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));
            Thread.sleep(1000);
            startTime = new Date(System.currentTimeMillis());//刷新时间
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

线程礼让yield

  • 让当前正在执行的线程暂停,但不阻塞
  • 令线程从运行状态转变为就绪状态
  • 令CPU重新调度,但不一定成功
public class TestYield {
    public static void main(String[] args) {
        MyYield myYield1 = new MyYield();
        MyYield myYield2 = new MyYield();

        new Thread(myYield1,"a").start();
        new Thread(myYield2,"b").start();
    }
}

class MyYield implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + ",start");
        Thread.yield();
        System.out.println(Thread.currentThread().getName() + ",over");
    }
}

线程强制执行join

  • join合并线程,此线程执行完再执行其他线程,其他线程阻塞
  • 类似于插队,霸占所有资源完成任务
public class TestJoin implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 77; i++) {
            System.out.println("插队,霸占所有资源" + i);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        //启动线程
        TestJoin testJoin = new TestJoin();
        Thread thread = new Thread(testJoin);
        thread.start();

        //主线程
        for (int i = 0; i < 1000; i++) {
            //在200以前是CPU调度多线程执行,20后是join执行,霸占资源
            if (i == 20){
                thread.join();
            }
            System.out.println("main:" + i);
        }
    }
}

线程状态观测

Thread.State,状态为以下之一:

  • NEW:暂未启动的线程
  • RUNNABLE:在执行的线程
  • BLOCKED:被阻塞等到监视器锁定的线程
  • WAITING:在等待另一个线程执行特定动作的线程
  • TIMED_WAITING:在等待另一个线程执行动作达到指定等待时间的线程
  • 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);

        //启动后状态
        thread.start();
        state = thread.getState();
        System.out.println(state);

        while (state != Thread.State.TERMINATED){
            Thread.sleep(100);
            state = thread.getState();//更新状态
            System.out.println(state);
        }
        
        //线程停止后无法再启动
    }
}

线程优先级

  • Java提供一个线程调度器监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定调度线程

  • 优先级由数字表示,范围为1-10:

    • Thread.MIN_PRIORITY = 1;
    • Thread.Max_PRIORITY = 10;
    • Thread.NORM_PRIORITY = 5;默认优先级
  • getPriority():获取优先级

  • setPriority(int num):改变优先级

先设置优先级再运行,设置了优先级调度还是由CPU决定

public class TestPriority {
    public static void main(String[] args) {
        //主线程默认优先级
        System.out.println(Thread.currentThread().getName() + "的优先级为:" + Thread.currentThread().getPriority());

        MyPriority myPriority = new MyPriority();
        Thread t1 = new Thread(myPriority);
        Thread t2 = new Thread(myPriority);
        Thread t3 = new Thread(myPriority);
        Thread t4 = new Thread(myPriority);
        Thread t5 = new Thread(myPriority);

        //设置优先级,启动
        t1.start();

        t2.setPriority(1);
        t2.start();

        t3.setPriority(4);
        t3.start();

        t4.setPriority(Thread.MAX_PRIORITY);//最大
        t4.start();

        t5.setPriority(5);
        t5.start();


    }
}

class MyPriority implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "的优先级为:" + Thread.currentThread().getPriority());
    }
}

输出结果

main的优先级为:5
Thread-0的优先级为:5
Thread-3的优先级为:10
Thread-4的优先级为:5
Thread-2的优先级为:4
Thread-1的优先级为:1

守护(daemon)线程

  • 线程分为用户线程守护线程
  • 虚拟机必须确保用户线程执行完毕
  • 虚拟机不必等待守护线程执行完毕
  • 如:后台记录,回收
  • setDaemon(true):设置为守护线程;默认为false,表示用户线程,一般线程都是用户线程

程序在运行完用户线程后结束,不需要等待守护线程运行结束

public class TestDaemon {
    public static void main(String[] args) {
        God god = new God();
        You you = new You();

        Thread thread = new Thread(god);
        thread.setDaemon(true); //默认为false,表示用户线程,一般线程都是用户线程

        thread.start(); //启动守护线程
        new Thread(you).start(); //启动用户线程
    }
}


//God,守护线程
class God implements Runnable{
    @Override
    public void run() {
        while (true){
            System.out.println("see");
        }
    }
}

//你,用户线程
class You implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            System.out.println("活");
        }
        System.out.println("=====结束了=====");
    }
}
posted @ 2022-04-12 11:30  chachan53  阅读(36)  评论(0编辑  收藏  举报