4.5多线程--线程状态

image.png

setPriority(int newPriority) 更改线程的优先级;
static void sleep(long milis)
void join() 插队,等待该线程终止
static void yield() 暂停当前正在执行的线程对象,并执行其他线程
boolean isAlive() 测试线程是否处于活动状态


停止线程

image.png
public class StopDemo implements Runnable{

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

        for (int i = 0; i < 1000; i++) {
            System.out.println("thread----main"+i);
            if(i == 500){
                stopDemo.stop();
                System.out.println("停掉子线程--------");
            }
        }
    }

    private boolean flag = true;

    @Override
    public void run() {
        while (flag){
            System.out.println("thread----run");
        }
    }

    public void stop(){
        this.flag = false;
    }
}

线程休眠

image.png
/*
模拟计时器
 */
public class SleepDemo implements Runnable {
    @Override
    public void run() {
        try {
            Date nowDate = new Date();
            while (true){
                Thread.sleep(1000);
                System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(nowDate));
                nowDate = new Date();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        SleepDemo sleepDemo = new SleepDemo();
        new Thread(sleepDemo).start();
    }
}

线程礼让

image.png
/*
线程礼让,回到同一起跑线,重新等待 CPU 调度,可能不成功。
 */
public class YieldDemo {
    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()+"线程结束了");
    }
}

线程插队 join

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

public class JoinDemo implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println("VIP 线程来了"+i);
        }
    }

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

        for (int i = 0; i < 200; i++) {
            System.out.println("主线程执行中"+i);
            if(i==100){
                try {
                    thread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

观察线程状态

public class WatchStateDemo {
    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);//NEW

        thread.start();
        state = thread.getState();
        System.out.println(state);//RUNNABLE

        while (thread.getState() != Thread.State.TERMINATED){
            Thread.sleep(150);
            state = thread.getState();
            System.out.println(state);//TIMED_WAITING  最后TERMINATED
        }
    }
}

线程优先级

image.png

守护线程

image.png
public class deamonDemo {
    public static void main(String[] args) {
        Deamon deamon = new Deamon();
        Person person = new Person();

        Thread deamonThread = new Thread(deamon);
        deamonThread.setDaemon(true);
        deamonThread.start();

        Thread personThread = new Thread(person);
        personThread.start();
    }
}

class Person implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 36500; i++) {
            System.out.println("每天愉快的活着");
        }
        System.out.println("===========goodbye world=============");
    }
}

class Deamon implements Runnable{
    @Override
    public void run() {
        while (true){
            System.out.println("上帝保有着你");
        }
    }
}

sleep 与 yield

sleep

  1. 当前线程从 Running 进入 Timed Waiting 状态(阻塞)
  2. 其他线程可以使用 interrupt 方法 打断正在睡眠的线程,这是 sleep 方法会抛出 InterruptedException
  3. 睡眠结束后的线程未必会立即执行
  4. 建议使用 TimeUnit 的 sleep 代替 Thread.sleep 获取更好的可读性
    yield
  5. 当前线程从 Running 进入 Runnable 就绪状态
  6. 具体的实现依赖于操作系统的任务调度器
/**
 * 线程被打断
 */
public class InterruptDemo {
    public static void main(String[] args) {
        Thread t1 = new Thread() {
            @Override
            public void run() {
                try {
                    System.out.println("t1 enter sleep^");
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    System.out.println("t1 is waked up");
                    e.printStackTrace();
                }
                System.out.println("t1 被唤醒了");
            }
        };

        t1.start();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t1.interrupt();
        System.out.println("main 继续执行……");
    }
}

案例--防止 CPU 占用100%
在没有利用CPU计算时,不要让 while(true)空转

while (true){
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
  • 可以用 wait 或 条件变量达到类似效果
  • 不同的是,后两种都需要加锁,并且需要相应的唤醒操作,一般适用于要进行同步的场景
  • sleep 适用于无需锁同步的场景

interrupt

打断 sleep, wait, join 等阻塞状态的线程
会清空打断状态

**
 * 打断 sleep 等阻塞状态的线程,会清空打断状态
 */
public class InterruptDemo1 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(()->{
            try {
                System.out.println("t1 睡眠……");
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        t1.start();
        TimeUnit.SECONDS.sleep(1);
        t1.interrupt();
        System.out.println("t1 被打断");
        System.out.println(t1.isInterrupted());// sleep wait join 等阻塞状态的线程被打断,会清空打断状态
    }
}
/**
 * 打断 正常运行状态的线程,是否停止由线程自己决定;
 */
public class InterruptDemo2 {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (true){
                boolean interrupted = Thread.currentThread().isInterrupted();
                if(interrupted){
                    break;
                }
                System.out.println("t1 正在执行");
            }
        }, "t1");
        thread.start();

        TimeUnit.SECONDS.sleep(1);
        thread.interrupt();
        System.out.println("t1 被打断了……");
    }
}
模式之两阶段终止(Two Phase Termination)

如何在线程 T1 中“优雅”的终止线程T2。
错误思路

  • 使用线程对象的 stop() 方法,会真正的杀死线程,如果这是线程锁住了共享资源,被杀死后,就再也没有机会释放锁了,其他线程永远无法获取锁
  • 使用 System.exit(int) 方法停止线程,会让整个程序停止


    image.png
/**
 * 两阶段终止模式(Two Phase Termination)
 * 模拟系统监控程序
 */
public class InterruptDemo3 {
    public static void main(String[] args) throws InterruptedException {
        TwoPhaseTermination twoPhaseTermination = new TwoPhaseTermination();
        twoPhaseTermination.start();

        Thread.sleep(3500);
        twoPhaseTermination.stop();
    }
}

class TwoPhaseTermination {
    //监控线程
    Thread monitor;

    //启动
    public void start(){
        monitor = new Thread(()->{
            while (true){
                Thread current = Thread.currentThread();
                //判断是否被打断,如果被打断,则善后、退出循环
                if(current.isInterrupted()){//另外一个静态方法 interrupted 会清除打断标记
                    System.out.println("正在处理善后工作……");
                    break;
                }
                //如果没有被打断,则睡眠 1 秒,执行监控逻辑代码
                try {
                    TimeUnit.SECONDS.sleep(1);// 被打断情况1
                    System.out.println("正在执行监控逻辑……");// 被打断情况2
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    current.interrupt();
                }
            }
        });
        monitor.start();
    }
    //停止
    public void stop(){
        monitor.interrupt();
    }
}
打断 park 线程
/**
 * interrupt 打断 park 线程
 * 被打断后 interrupt:true  再 park 就失效了
 */
public class InterruptDemo4 {
    public static void main(String[] args) {
        test();
    }
    public static void test(){
        Thread t = new Thread(()->{
            System.out.println("线程正在执行");
            System.out.println("park");
            LockSupport.park();
            System.out.println("unpark");
//            System.out.println("打断状态:"+Thread.currentThread().isInterrupted());
            System.out.println("打断状态:"+Thread.interrupted());

            LockSupport.park();
            System.out.println("unpark");
        });
        t.start();

        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t.interrupt();
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • ![Flask](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAW...
    极客学院Wiki阅读 7,269评论 0 3
  • 不知不觉易趣客已经在路上走了快一年了,感觉也该让更多朋友认识知道易趣客,所以就谢了这篇简介,已做创业记事。 易趣客...
    Physher阅读 3,441评论 1 2
  • 双胎妊娠有家族遗传倾向,随母系遗传。有研究表明,如果孕妇本人是双胎之一,她生双胎的机率为1/58;若孕妇的父亲或母...
    邺水芙蓉hibiscus阅读 3,722评论 0 2
  • 晴天,拥抱阳光,拥抱你。雨天,想念雨滴,想念你。 我可以喜欢你吗可以啊 我还可以喜欢你吗可以,可是你要知道我们不可...
    露薇霜凝阅读 1,239评论 1 2