多线程详解(二)

目录

一、线程状态

1.1 五大状态

1.2 停止线程

1.3 线程休眠

1.4 线程礼让 

1.5 在线强制执行 

1.6 线程状态观测

二、线程优先级

三、守护线程

一、线程状态

1.1 五大状态

方法说明
setPriority(int newPriority)更改线程的优先级
static void sleep(long millis)在指定的毫秒数内让当前正在执行的线程体休眠
void join()等待该线程终止
static void yield()暂停当前正在执行的线程对象,并执行其他线程
void interrupt()中断线程,别用这个方式
boolean isAlive()测试线程是否处于活动状态

1.2 停止线程

1)不推荐使用JDK提供的stop()、destory()方法【已废弃】

2)推荐线程自己停下来

3)建议使用一个标志位进行终止变量,当flag=false,则终止线程运行

案例:模拟网络延时 ---> 放大问题的发生性

public class TestStop implements Runnable{
    //1.设置标志位
    private boolean flag=true;
    @Override
    public void run() {
        int i=0;
        while(flag){
            System.out.println("run...Thread "+i++);
        }
    }

    //2.设置一个公开的方法停止线程,转换标志位
    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 < 1000; i++) {
            System.out.println("main "+i);
            if(i==900){
                //调用stop方法切换标志位,让线程停止
                testStop.stop();
                System.out.println("线程停止");
            }
        }
    }
}

运行结果:

1.3 线程休眠

1)sleep(时间)指定当前线程阻塞的毫秒数   【1000毫秒=1秒】

2)sleep存在异常InterruptedException

3)sleep时间达到后线程进入就绪状态

4)sleep可以模拟网络延时,倒计时等

5)没一个对象都有一个锁,sleep不会释放锁

演示案例1:模拟倒计时

//模拟倒计时
public class TestSleep02{
    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) {
        try {
            tenDown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行结果:10秒的倒计时,间隔一秒

演示案例2:获取系统当前时间


public class TestSleep02{

    public static void main(String[] args) {
        //打印当前系统时间
        //获取系统当前时间
        Date startTime = new Date(System.currentTimeMillis());
        while(true){
            try {
                Thread.sleep(1000);
                //格式工厂
                System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));
                //更新时间
                startTime = new Date(System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}

运行结果:

1.4 线程礼让 

1)礼让线程,让当前正在执行的线程暂停,但不阻塞

2)将线程从运行态转为就绪态

3)让cpu重新调度,礼让不一定成功,要看cpu心情

public class TestYield {
    public static void main(String[] args) {
        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()+" 线程开始执行");
        //礼让
        Thread.yield();
        System.out.println(Thread.currentThread().getName()+" 线程停止执行");
    }
}

礼让成功:

礼让不成功:

1.5 在线强制执行 

Join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞

可以想象成插队

public class TestJoin implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("线程vip来了 "+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++) {
            if(i==200){
                thread.join();//插队
            }
            System.out.println("main "+i);
        }
    }
}

运行结果:

1.6 线程状态观测

线程状态:Thread.State

线程可以处于以下几个状态之一:

1)new        尚未启动的线程处于此状态

2)runnable        在Java虚拟机中执行的线程处于此状态

3)blocked        被阻塞等待监视器锁定的线程处于此状态

4)waiting        正在等待另一个线程执行特定动作的线程处于此状态

5)timed_waiting        正在等待另一个线程执行动作达到指定等待时间的线程处于此状态

6)terminated        已退出的线程处于此状态

一个线程可以在给定时间点处于一个状态,这些状态是不反映任何操作系统线程状态的虚拟机状态。

死亡之后的线程不能再次被启动

案例:测试线程状态

public class TestState {
    public static void main(String[] args) throws InterruptedException {
        //lambda表达式
        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);//new

        //观察启动后
        thread.start();//启动线程
        state=thread.getState();
        System.out.println(state);//run

        while(state != Thread.State.TERMINATED){
            Thread.sleep(100);
            //更新线程状态
            state=thread.getState();
            System.out.println(state);
        }

    }
}

运行结果:

二、线程优先级

1)Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行

2)线程的优先级用数字表示,范围从1~10

        Thread.MIN_PRIORITY=1;

        Thread.MAX_PRIORITY=10;

        Thread.NORM_PRIORITY=5;

3)使用以下方式改变或获取线程优先级

        getPriority().setPriority(int xxx)

优先级低只是意味着获得调度的概率低,并不是优先级低就不会被调用了,这都是看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);

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

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

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

        t4.setPriority(Thread.MAX_PRIORITY);//最高级
        t4.start();
    }
}

class MyPriority implements Runnable{
    @Override
    public void run() {
        //打印线程名字和优先级
        System.out.println(Thread.currentThread().getName()+" ---> "+Thread.currentThread().getPriority());
    }
}

运行结果:大多数情况下,优先级高的先跑,但不绝对

三、守护线程

1)线程分为 用户线程 守护线程 

2)虚拟机必须确保用户线程执行完毕

3)虚拟机不用等待守护线程执行完毕

4)如:后台记录操作日志、监控内存、垃圾回收(gc)等

案例:测试守护线程

//上帝守护你
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();//用户线程启动
    }
}

//上帝
class God implements Runnable{
    @Override
    public void run() {
        while(true){
            System.out.println("good luck");
        }
    }
}

//你
class You implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 36500; i++) {
            System.out.println("happy");
        }
        System.out.println("goodbye");
    }
}

运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值