多线程原理与实战【03 线程的核心原理】

线程的核心原理

线程的调度与时间片

时间片:CPU在时间毫秒在维度进行分段,每一小段叫作一个CPU时间片。
调度:分时调度模型(系统平均分配CPU在时间片)、抢占式调度模型(系统按优先级分配CPU时间片,优先级相同随机选择一个,优先级高在线程获得CPU时间片相对多一些)

线程的优先级

public class Thread implements Runnable {
    //该属性保存一个Thread实例在优先级,即[1,10]的值
    private int  priority;
    //最小值
    public final static int MIN_PRIORITY = 1;
	//默认值
    public final static int NORM_PRIORITY = 5;
    //最大值
    public final static int MAX_PRIORITY = 10;
    //获取线程的优先级
    public final int getPriority() {
        return priority;
    }
    //设置线程在优先级
    public final void setPriority(int newPriority) {
        ThreadGroup g;
        checkAccess();
        if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
            throw new IllegalArgumentException();
        }
        if((g = getThreadGroup()) != null) {
            if (newPriority > g.getMaxPriority()) {
                newPriority = g.getMaxPriority();
            }
            setPriority0(priority = newPriority);
        }
    }
}    
package com.ryder.code;

public class PriorityDemo {
    static class PrioritySetThread extends Thread {
        static int threadNo = 1;

        public PrioritySetThread() {
            super("thread-" + threadNo);
            threadNo++;
        }

        public long opportunities = 0;

        public void run() {
            for (int i = 0; i < 20000000000L; i++) {
                opportunities++;
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        PrioritySetThread[] threads = new PrioritySetThread[10];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new PrioritySetThread();
            //设置优先级[1,10]
            threads[i].setPriority(i + 1);
        }
        for (int i = 0; i < threads.length; i++) {
            threads[i].start();
        }
        Thread.sleep(1000);
        for (int i = 0; i < threads.length; i++) {
            threads[i].stop();
        }
        for (int i = 0; i < threads.length; i++) {
            System.out.println(threads[i].getName() +
                    "---优先级:" + threads[i].getPriority() +
                    "---机会值: " + threads[i].opportunities);
        }
    }
}
thread-1---优先级:1---机会值: 0
thread-2---优先级:2---机会值: 0
thread-3---优先级:3---机会值: 53761
thread-4---优先级:4---机会值: 0
thread-5---优先级:5---机会值: 23844913
thread-6---优先级:6---机会值: 2532408527
thread-7---优先级:7---机会值: 10179683260
thread-8---优先级:8---机会值: 10270675487
thread-9---优先级:9---机会值: 6553110054
thread-10---优先级:10---机会值: 10436151582

某个线程的实例属性opportunities的值越大,就表明获得的CPU时间片越多。

线程的生命周期

    public enum State {
        
        NEW, //新建
        
        RUNNABLE, //可执行:就绪、运行状态

        BLOCKED, //阻塞

        WAITING, //等待
     
        TIMED_WAITING, //计时等待

        TERMINATED;  //终止
    }
package com.ryder.code;

import java.util.ArrayList;
import java.util.List;

public class StatusDemo {
    //每个线程执行的轮次
    public static final long MAX_COUNT = 5;
    //线程编号
    public static int threadNo = 0;
    //全局的静态线程列表
    static List<Thread> threadList = new ArrayList<>();

    //输出静态线程列表中每个线程的状态
    private static void printThreadStatus() {
        for (Thread thread : threadList) {
            System.out.println(thread.getName() + "状态为:" + thread.getState());
        }
    }

    //向全局的静态线程列表加入线程
    private static void addStatusThread(Thread thread) {
        threadList.add(thread);
    }

    static class StatusDemoThread extends Thread {
        public StatusDemoThread() {
            super("statusPrintThread" + (++threadNo));
            addStatusThread(this);
        }

        @Override
        public void run() {
            System.out.println(getName() + ",状态为" + getState());
            for (int i = 0; i < MAX_COUNT; i++) {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                printThreadStatus();
            }
            System.out.println(getName() + "---运行结束");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        addStatusThread(Thread.currentThread());
        Thread statusDemoThread01 = new StatusDemoThread();
        System.out.println(statusDemoThread01.getName() + "--状态为:" + statusDemoThread01.getState());
        Thread statusDemoThread02 = new StatusDemoThread();
        System.out.println(statusDemoThread02.getName() + "--状态为:" + statusDemoThread02.getState());
        Thread statusDemoThread03 = new StatusDemoThread();
        System.out.println(statusDemoThread03.getName() + "--状态为:" + statusDemoThread03.getState());
        statusDemoThread01.start();
        Thread.sleep(500);
        statusDemoThread02.start();
        Thread.sleep(500);
        statusDemoThread03.start();
    }
}

statusPrintThread1--状态为:NEW
statusPrintThread2--状态为:NEW
statusPrintThread3--状态为:NEW
statusPrintThread1,状态为RUNNABLE
main状态为:RUNNABLE
statusPrintThread1状态为:RUNNABLE
statusPrintThread2状态为:RUNNABLE
statusPrintThread3状态为:NEW
statusPrintThread2,状态为RUNNABLE
main状态为:TIMED_WAITING
main状态为:TIMED_WAITING
statusPrintThread1状态为:RUNNABLE
statusPrintThread2状态为:RUNNABLE
statusPrintThread3状态为:NEW
statusPrintThread1状态为:RUNNABLE
statusPrintThread2状态为:TIMED_WAITING
statusPrintThread3状态为:NEW
statusPrintThread3,状态为RUNNABLE
main状态为:TERMINATED
statusPrintThread1状态为:RUNNABLE
main状态为:TERMINATED
statusPrintThread1状态为:BLOCKED
main状态为:TERMINATED
statusPrintThread1状态为:BLOCKED
statusPrintThread2状态为:BLOCKED
statusPrintThread3状态为:RUNNABLE
statusPrintThread2状态为:BLOCKED
statusPrintThread2状态为:RUNNABLE
statusPrintThread3状态为:TIMED_WAITING
statusPrintThread3状态为:TIMED_WAITING
main状态为:TERMINATED
main状态为:TERMINATED
statusPrintThread1状态为:BLOCKED
statusPrintThread2状态为:RUNNABLE
statusPrintThread3状态为:RUNNABLE
main状态为:TERMINATED
statusPrintThread1状态为:RUNNABLE
statusPrintThread2状态为:TIMED_WAITING
statusPrintThread3状态为:RUNNABLE
statusPrintThread1状态为:TIMED_WAITING
statusPrintThread2状态为:TIMED_WAITING
statusPrintThread3状态为:RUNNABLE
main状态为:TERMINATED
main状态为:TERMINATED
statusPrintThread1状态为:RUNNABLE
statusPrintThread2状态为:RUNNABLE
statusPrintThread3状态为:BLOCKED
main状态为:TERMINATED
statusPrintThread1状态为:RUNNABLE
statusPrintThread2状态为:TIMED_WAITING
statusPrintThread3状态为:RUNNABLE
statusPrintThread1状态为:RUNNABLE
statusPrintThread2状态为:TIMED_WAITING
statusPrintThread3状态为:TIMED_WAITING
statusPrintThread1---运行结束
main状态为:TERMINATED
main状态为:TERMINATED
statusPrintThread1状态为:TERMINATED
statusPrintThread2状态为:RUNNABLE
statusPrintThread3状态为:RUNNABLE
statusPrintThread1状态为:TERMINATED
statusPrintThread2状态为:RUNNABLE
statusPrintThread3状态为:TIMED_WAITING
statusPrintThread2---运行结束
main状态为:TERMINATED
statusPrintThread1状态为:TERMINATED
statusPrintThread2状态为:TERMINATED
statusPrintThread3状态为:RUNNABLE
statusPrintThread3---运行结束

通过结果可以看出来,新建之后,没有启动之前为NEW,调用了start()之后,状态为RUNNABLE,调用Thread.sleep()方法后,线程状态变为TIMED_WAITING,等结束后又变为RUNNABLE,线程执行完成后,状态为TERMINATED。

使用Jstack工具查看线程状态

有时,服务器的CPU占用率一直很高,程序是正常运行的,那么如何查看占用CPU的线程状态呢?
有一种比较快捷的办法就是使用Jstack工具。

Jstack 命令语法格式
jstack //pid 表示java进程id,可以用jps命令查看

Jstack指令输出的重要信息:

  1. tid: 线程实例在JVM进程中的id
  2. nid: 线程实例在操作系统中对应的底层线程的线程id
  3. prio: 线程实例在JVM进程中的优先级
  4. os_prio: 线程实例在操作系统中对应的底层线程的优先级
  5. 线程状态:runnable 、waiting 、blocked等。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值