多线程的概念

多线程

同时执行多个任务,例如一个人一边听歌,一边跳舞

继承Thread类实现多线程的方式

定义一个MyThread类继承Thread类,重写里面的run方法

java 复制代码
package com.itxs.demo01;

/**
 * @Classname : MyThread
 * @Description : TODO 自定义线程继承Thread类
 * @Author : lin_refuel@qq.com
 */
public class MyThread extends Thread{
    @Override
    public void run() {
        //super.run();
        for (int i = 0; i < 20; i++) {
            System.out.println("i = " + i);
        }
    }
}

测试多线程类

java 复制代码
package com.itxs.demo01;

/**
 * @Classname : demo01
 * @Description : TODO 多线程的测试类
 * @Author : lin_refuel@qq.com
 */
public class demo01 {
    public static void main(String[] args) {
    // 线程对象创建
        MyThread my01 = new MyThread();
        MyThread my02 = new MyThread();
        MyThread my03 = new MyThread();
        MyThread my04 = new MyThread();
        //开启线程的方法start
        my01.start();
        my02.start();
        my03.start();
        my04.start();
    }
}

线程名字的获取和设置

自定义线程继承Thread类

java 复制代码
package com.itxs.demo02;

/**
 * @Classname : MyThread
 * @Description : TODO 自定义线程 - 继承Thread类
 * @Author : lin_refuel@qq.com
 */
public class MyThread extends Thread {
    public MyThread() {
    }

    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            // this.getName获取类中自己的Name值
            System.out.println(this.getName() + " i =" + i);
        }
    }
}

测试线程

java 复制代码
package com.itxs.demo02;

/**
 * @Classname : demo01
 * @Description : TODO 多线程名字设置的方式
 * @Author : lin_refuel@qq.com
 */
public class demo01 {
    public static void main(String[] args) {
         //创建线程对象
        // 方式一:通过构造方法进行设置每个线程名字
        MyThread my01 = new MyThread("线程01");
        MyThread my02 = new MyThread("线程02");
        MyThread my03 = new MyThread("线程03");
        MyThread my04 = new MyThread();
        // 方式二:通过方法setName设置线程名字
//        my01.setName("线程01");
//        my02.setName("线程02");
//        my03.setName("线程03");
        my04.setName("线程04");
        //开启线程
        my01.start();
        my02.start();
        my03.start();
        my04.start();
    }
}

运行结果:

获取正在运行的线程对象

获取正在运行的线程

java 复制代码
Thread.currentThread()

通过上面的方法,获取到每个运行线程的名字

java 复制代码
package com.itxs.demo02;

/**
 * @Classname : MyThread
 * @Description : TODO 自定义线程(输出0-19) - 继承Thread类
 * @Author : lin_refuel@qq.com
 */
public class MyThread extends Thread {
    public MyThread() {
    }

    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            // this.getName获取类中自己的Name值
            System.out.println(Thread.currentThread().getName() + " i =" + i);
        }
    }
}
java 复制代码
package com.itxs.demo02;

/**
 * @Classname : demo03
 * @Description : TODO 获取每个正在运行的线程的方法
 * @Author : lin_refuel@qq.com
 */
public class demo03 {
    public static void main(String[] args) {
          // 创建几个线程对象,设置每个线程的名字
        MyThread my01 = new MyThread("多线程01");
        MyThread my02 = new MyThread("多线程02");
        MyThread my03 = new MyThread("多线程03");
        MyThread my04 = new MyThread("多线程04");
        //开启线程
        my01.start();
        my02.start();
        my03.start();
        my04.start();
        // main 其实也是一个线程,但是却是主线程
        // 输出0-19
        //设置主线程名字的方法 Thread.currentThread是获取正在运行的线程
        //setName是设置名字
        Thread.currentThread().setName("主线程");
        for (int i = 0; i < 20; i++) {
            System.out.println( Thread.currentThread().getName()+"i = " + i);
        }
    }
}

线程调度

  • 两种线程调度模型

    • 分时调度模型:所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间

    • 抢占调度模型:优先让优先级高的线程使用 CPU,如果线程的欧优先级相同,那么随机选择一个,优先级高的线程获取的 CPU 占用时间会相对多一丢丢丢丢丢......

    Java 使用的是抢占式的调度模型

线程优先级设置

  • Thread 类中设置和获取线程优先级的方法

    • public final int getPriority():返回次线程的优先级

    • public final void setProiority(int newPriority):更改次线程的优先级

自定义的线程类-继承Thread类

java 复制代码
package com.itxs.demo02;

/**
 * @Classname : MyThread
 * @Description : TODO 自定义线程(输出0-19) - 继承Thread类
 * @Author : lin_refuel@qq.com
 */
public class MyThread extends Thread {
    public MyThread() {
    }

    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            // this.getName获取类中自己的Name值
            System.out.println(Thread.currentThread().getName() + " i =" + i);
        }
    }
}

优先级测试

java 复制代码
package com.itxs.demo02;

/**
 * @Classname : demo02
 * @Description : TODO 线程调度测试
 * @Author : lin_refuel@qq.com
 */
public class demo02 {
    public static void main(String[] args) {
        // 创建线程对象
        MyThread mt01 = new MyThread("线程01");
        MyThread mt02 = new MyThread("线程02");
        MyThread mt03 = new MyThread("线程03");
        //修改线程的优先级
        mt01.setPriority(Thread.MIN_PRIORITY);//1
        mt02.setPriority(Thread.NORM_PRIORITY);//5
        mt03.setPriority(Thread.MAX_PRIORITY);//10
        // 线程的优先级输出
//        System.out.println(mt01.getPriority());
//        System.out.println(mt02.getPriority());
//        System.out.println(mt03.getPriority());
        //开启线程测试那个线程优先完成
        mt03.start();
        mt02.start();
        mt01.start();
    }
}

线程控制

方法名 说明
static void sleep(long ms) 使当前正在执行的线程停留指定的毫秒数
void join() 等待这个进程死亡
void setDaemon(boolean on) 将此线程标记为守护进程,当运行线程都是守护线程时,JVM 将退出

sleep方法

案例:华山论剑

自定义线程类

java 复制代码
package com.itxs.demo02;

/**
 * @Classname : MyThread
 * @Description : TODO 自定义一个线程 - 继承Thread类
 * @Author : lin_refuel@qq.com
 */
public class MyThread extends Thread{
    public MyThread() {
    }

    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i = 1; i <=20 ; i++) {
            System.out.println(Thread.currentThread().getName() + "出了第"+i+"招");
            try {
                Thread.sleep(1000);//停留一秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

sleep测试类

java 复制代码
package com.itxs.demo02;

/**
 * @Classname : demo02
 * @Description : TODO 线程测试 - sleep
 * @Author : lin_refuel@qq.com
 */
public class demo02 {
    public static void main(String[] args) {
         //创建线程对象
        MyThread mt01 = new MyThread("黄固");
        MyThread mt02 = new MyThread("欧阳锋");
        MyThread mt03 = new MyThread("段智兴");
        MyThread mt04 = new MyThread("洪七公");
        //开启线程
        mt01.start();
        mt02.start();
        mt03.start();
        mt04.start();
    }
}

join方法

歌曲《天下》,原唱:张杰,翻唱:池瑶和高鱼

java 复制代码
package com.itxs.demo03;

/**
 * @Classname : MyThread
 * @Description : TODO
 * @Author : lin_refuel@qq.com
 */
public class MyThread extends Thread {
    public MyThread() {
        super();
    }

    public MyThread(String name) {
        super(name);
    }

    // 定义一个数组存放歌词
    String[] song = {"烽烟起寻爱似浪淘沙",
            "遇见她如春水映梨花",
            "挥剑断天涯",
            "相思轻放下"
    };

    @Override
    public void run() {
        for (int i = 0; i < song.length; i++) {
            System.out.println(Thread.currentThread().getName() + "正在唱:" + song[i]);
        }
    }
}

测试-张杰唱完后,两个翻唱继续唱

java 复制代码
package com.itxs.demo03;

/**
 * @Classname : demo01
 * @Description : TODO
 * @Author : lin_refuel@qq.com
 */
public class demo01 {
    public static void main(String[] args) throws InterruptedException {
        //创建线程
        MyThread mt01 = new MyThread("张杰");
        MyThread mt02 = new MyThread("池瑶");
        MyThread mt03 = new MyThread("高鱼");
        //开启线程
        mt01.start();
        mt01.join();//等待张杰唱完,mt01执行完后执行后面的线程
        mt02.start();
        mt03.start();
    }
}

setDaemon()

守护线程,总结就是当创建的线程对象设置为守护线程后,主线程里面的内容执行完后,所有开启的多线程都会停止执行
自定义的线程,执行20次循环

java 复制代码
package com.itxs.demo04;

/**
 * @Classname : MyThread
 * @Description : TODO - 自定义线程
 * @Author : lin_refuel@qq.com
 */
public class MyThread extends Thread{
    public MyThread() {
        super();
    }

    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println(Thread.currentThread().getName()+"报数:"+i);
        }
    }
}

测试守护线程

java 复制代码
package com.itxs.demo04;

/**
 * @Classname : demo01
 * @Description : TODO
 * @Author : lin_refuel@qq.com
 */
public class demo01 {
    public static void main(String[] args) {
         //创建线程对象
        MyThread mt01 = new MyThread("1号");
        MyThread mt02 = new MyThread("2号");
        MyThread mt03 = new MyThread("3号");
        System.out.println("开始报数");
        //mt01,02,03设置为守护线程
        mt01.setDaemon(true);
        mt02.setDaemon(true);
        mt03.setDaemon(true);
        // 线程开启
        mt01.start();
        mt02.start();
        mt03.start();

        // 主线程执行三次循环
        for (int i = 0; i < 3; i++) {
            System.out.println("报数中");
        }
        System.out.println("停止报数");
    }
}

线程的生命周期

  • 新建:创建线程对象(通过 start() 进入下一个环节)

  • 就绪:有执行资格,没有执行权(抢占 CPU 的执行权)

  • 运行:有执行资格,有执行权(可能被其他线程抢走 CPU 的执行权,则回到就绪状态,若遇到阻塞式方法,则失去运行权和执行这个,等待,当阻塞方法调用结束之后,回到就绪状态)

  • 死亡:线程死亡,成为垃圾

相关推荐
XiaoLeisj1 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
paopaokaka_luck1 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计
dayouziei1 小时前
java的类加载机制的学习
java·学习
Yaml43 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
小小小妮子~3 小时前
Spring Boot详解:从入门到精通
java·spring boot·后端
hong1616883 小时前
Spring Boot中实现多数据源连接和切换的方案
java·spring boot·后端
aloha_7894 小时前
从零记录搭建一个干净的mybatis环境
java·笔记·spring·spring cloud·maven·mybatis·springboot
记录成长java4 小时前
ServletContext,Cookie,HttpSession的使用
java·开发语言·servlet
睡觉谁叫~~~4 小时前
一文解秘Rust如何与Java互操作
java·开发语言·后端·rust
程序媛小果5 小时前
基于java+SpringBoot+Vue的旅游管理系统设计与实现
java·vue.js·spring boot