Java多线程学习笔记(2)

线程状态

创建状态 ----> 就绪状态 ----> 运行状态 ----> 死亡状态

运行状态会回到就绪状态

线程方法

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

不推荐使用stop和destory方法关闭程序。

1.线程休眠

  • sleep(时间)指定当前线程阻塞的毫秒数(1s=1000ms);
  • sleep存在异常InterruptedException;
  • sleep时间达到后线程进入就绪状态;
  • sleep可以模拟网络延时,倒计时等;
  • 每一个对象都有一个锁,sleep不会释放锁。

例1:

package com.mpj.demo;

public class Test5 implements Runnable {
    private int num = 10;
    @Override
    public void run() {
        while (true){
            if (num<=0){
                break;
            }
            //模拟延迟
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"拿到了第"+num--+"票");
        }
    }

    public static void main(String[] args) {
        Test5 test5 = new Test5();
        new Thread(test5,"张三").start();
        new Thread(test5,"李四").start();
        new Thread(test5,"赵五").start();
    }
}

模拟网络延迟:放大问题的发生性

例2:

package com.mpj.demo2;
//模拟倒计时
public class Test1 {
    public static void main(String[] args) {
        try {
            countdown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public static void countdown() throws InterruptedException {
        int num = 10;
        while (true){
            Thread.sleep(1000);//1s=1000ms 抛出异常
            System.out.println(num--);
            if(num<=0){
                break;
            }
        }
    }

}

2.线程礼让

  • 礼让线程,让当前正在执行的线程暂停,但不阻塞;
  • 将线程从运行状态转为就绪状态;
  • 让CPU重新调用,礼让不一定成功!看CPU心情!

例:

package com.mpj.demo2;

public class TestYield {
    public static void main(String[] args) {
        Yield yield = new Yield();
        new Thread(yield,"a").start();
        new Thread(yield,"b").start();

    }
}

class Yield implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"-->线程开启");
        Thread.yield();
        System.out.println(Thread.currentThread().getName()+"-->线程结束");
    }
}

3.线程强制执行

  • Join合并线程,待此线程执行完成后,在执行其他线程,其他线程阻塞
  • 想象成插队

例:

package com.mpj.demo2;

public class TestJoin implements Runnable{
    public static void main(String[] args) {
        TestJoin testJoin = new TestJoin();
        Thread thread = new Thread(testJoin);
        thread.start();

        for (int i = 0; i < 100; i++) {
            if(i==50){
                try {
                    thread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("main..."+i);
        }
    }
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println("join..."+i);
        }
    }
}

线程状态观测 Thread.State

​ 线程状态,线程可处于一下状态之一:

- NEW(尚未启动的线程处于此状态)
- RUNNABLE(在Java虚拟机中执行的线程处于此状态)
- BLOCKED(在阻塞等待监视器锁定的线程处于此状态)
- WAITING(在等在另一个线程执行执行特定动作的线程处于此状态)
- TIMED_WAITING(正在等待另一个线程执行动作达到指定等待时间的线程处于此状态)
- TERMINATED(以退出的线程处于此状态)

例:

package com.mpj.demo2;

public class TestState {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread();
        for (int i = 0; i < 5; i++) {
            Thread.sleep(1000);
            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(1000);
            state = thread.getState();
            System.out.println(state);
        }
        
        thread.start();//线程终止不能在启动

    }
}

线程的优先级

  • Java提供一个线程调度器来监控程序启动后进入就绪的所有线程,线程调度器按照优先级来决定调度哪个线程。
  • 优先级用数字表示 [1-10]
    • Thread.MIN_PRIORITY = 1;
    • Thread.MAX_PRIORITY = 10;
    • Thread.NORM_PRIORITY = 5;
  • 方法
    • getPriority().setPriority(int args)
  • main方法默认优先级为5
  • 先设置优先级再启动
  • 优先级低不是调度概率低,还是得看CPU调度

例:

package com.mpj.demo2;

public class TestPriority {
    public static void main(String[] args) {
        //main优先级
        System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
        Priority priority = new Priority();
        Thread t1 = new Thread(priority);
        Thread t2 = new Thread(priority);
        Thread t3 = new Thread(priority);
        Thread t4 = new Thread(priority);

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

        t2.setPriority(3);
        t2.start();

        t3.setPriority(6);
        t3.start();

        t4.setPriority(10);
        t4.start();
    }
}

class Priority implements Runnable{
    @Override
    public void run() {
        //输出优先级
        System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
    }
}

控制台:

main-->5
Thread-0-->5
Thread-3-->10
Thread-1-->3
Thread-2-->6

虽然设置了优先级但是最后的调度还得看CPU

守护(daemon)线程

  • 线程分为用户线程和守护线程
  • 虚拟机必须确保用户线程执行完毕
  • 虚拟机不用等待守护线程执行完毕
  • 如,后台记录操作日志,监控内存,垃圾回收等待...

例:

package com.mpj.demo2;

public class TestDaemon {
    public static void main(String[] args) {
        God god = new God();
        You2 you = new You2();
        //守护线程
        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("上帝守护着你!");
        }
    }
}
//用户线程
class You2 implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 30000; i++) {
            System.out.println("你活了--"+i);
        }
    }
}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Java多线程学习 [-] 一扩展javalangThread类 二实现javalangRunnable接口 三T...
    影驰阅读 3,155评论 1赞 18
  • 本文主要讲了java中多线程的使用方法、线程同步、线程数据传递、线程状态及相应的一些线程函数用法、概述等。 首先讲...
    李欣阳阅读 2,649评论 1赞 15
  • 一、认识多任务、多进程、单线程、多线程 要认识多线程就要从操作系统的原理说起。 以前古老的DOS操作系统(V 6....
    GT921阅读 1,131评论 0赞 3
  • 文章来源:http://www.54tianzhisheng.cn/2017/06/04/Java-Thread/...
    beneke阅读 2,025评论 0赞 1
  • 一、线程的生命周期 线程状态转换图: 1、新建状态 用new关键字和Thread类或其子类建立一个线程对象后,该线...
    二月夜阅读 527评论 0赞 0

友情链接更多精彩内容