多线程的概念

多线程

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

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

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

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);
        }
    }
}

测试多线程类

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类

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);
        }
    }
}

测试线程

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();
    }
}

运行结果:
在这里插入图片描述

获取正在运行的线程对象

获取正在运行的线程

Thread.currentThread()

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

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);
        }
    }
}
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类

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);
        }
    }
}

优先级测试

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方法

案例:华山论剑

自定义线程类

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测试类

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方法

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

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]);
        }
    }
}

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

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次循环

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);
        }
    }
}

测试守护线程

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 的执行权,则回到就绪状态,若遇到阻塞式方法,则失去运行权和执行这个,等待,当阻塞方法调用结束之后,回到就绪状态)

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

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-01-09 18:46:04       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-09 18:46:04       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-09 18:46:04       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-09 18:46:04       20 阅读

热门阅读

  1. Kafka单节点部署

    2024-01-09 18:46:04       30 阅读
  2. php实现定时任务

    2024-01-09 18:46:04       32 阅读
  3. LC509. 斐波那契数

    2024-01-09 18:46:04       34 阅读
  4. Linux自动化部署脚本

    2024-01-09 18:46:04       41 阅读
  5. Object-c初步学习 四

    2024-01-09 18:46:04       31 阅读
  6. 【低功耗】芯片低功耗-硬件

    2024-01-09 18:46:04       39 阅读
  7. 彻底卸载Microsoft Edge:一步步指南

    2024-01-09 18:46:04       42 阅读
  8. 骑砍战团MOD开发(34)-光照系统

    2024-01-09 18:46:04       45 阅读