JAVA多线程

多线程

Java 多线程编程

Java 给多线程编程提供了内置的支持。 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

多线程是多任务的一种特别的形式,但多线程使用了更小的资源开销。

这里定义和线程相关的另一个术语 - 进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程。一个线程不能独立的存在,它必须是进程的一部分。一个进程一直运行,直到所有的非守护线程都结束运行后才能结束。

多线程能满足程序员编写高效率的程序来达到充分利用 CPU 的目的。

线程的生命周期

NEW

RUNNABLE

RUNNING

BLOCKED

TERMINATED

线程的NEW状态

当我们使用关键字new创建一个Tread对象时候,它并不处于任何执行状态,因为 没有调用start方法启动,此时该线程不存在,只是单纯的处于Tread对象状态

线程的RUNNABLE状态

通过start方法进入RUNNABLE状态,进入RUNNABLE状态必须调用start方法,此时才会真正的在JVM中创建 一个线程,此时的线程并没有执行,处于等待CPU调度的可执行状态

线程的RUNNING状态

CPU轮询或者其他方式从可执行队列中选中了线程,此时才可以执行自己的逻辑代码,正在RUNNING状态的线程事实上也是RUNNABLE的,但是反之不成立

1.直接进入TERMINATEDE状态,比如调用JDK的stop方法

2.进入BLOCKED状态,比如调用了sleep,或者 wait方法.

3.进行某个阻塞IO,比如网络数据的读写二进入了BLOCKED

4.获取某个锁资源,从而加入锁的阻塞队列中进入了BLOCKED状态

5.由于CPU的调用轮询使得该线程放弃执行,进入了RUNNABLE状态

6.线程主动调用yield方法,放弃CPU执行权,进入RUNNABLE状态

线程的BLOCKED状态

1.直接进入TERMINATED状态,比如调用JDK的stop方法

2.线程阻塞导致操作结束 ,进入到RUNNABLE状态

4.线程完成了执行时间的休眠后,进入RUNNABLE状态

5.线程获取到了某个锁资源,进入RUNNABLE状态

6.线程阻塞过程中被打断,比如其他线程调用了interrupt方法,进入RUNNABLE状态

线程的TERMINATED状态

线程的最终状态,此时线程不会切换到任何其他的状态,并且生命周期已经结束

1.线程的正常运行结束

2.线程运行出错意外结束

JVM Crash ,导致所有线程都结束

线程start方法剖析

start 方法的底层

核心是start0这个本地方法,也就是JNI方法

在开始执行线程时,JVM会调用该线程的run方法,run方法是被JNI方法的start0()调用的

1.Tread被构造后的NEW状态,treadStatus属性为0

2.不能两次启动Tread,否则会出现IllegalTreadStateException

3.线程启动后被加入到TreadGroup组中

4.一个线程的生命周期 结束,到了TERMINATED状态,在调用start方法是不允许的,无法回到RUNNABLE/RUNNING状态的,也会出现IllegalTreadStateException

模板设计的应用

Tread的run 和 start是一个典型的模板设计模式,父类编写算法结构代码,子类实现逻辑细节,线程真正的执行逻辑是在run方法中,通常把run方法称为线程的执行单元,所以用start方法启动线程,重写 run方法实现具体逻辑

引入Runable接口,线程的创建方式?

线程的创建方式

创建线程有两种方式,一种是创建Tread,一种是实现Runnable接口,这种说法是错误不严谨的

准确来讲,创建线程只有一种方式,就是构造Thread类,而实现线程执行单元(也就是 run方法)有两种方式,一种是重写Tread的run方法,第二种是实现Runnable接口的run方法,并且将Runnable实例用作构造Thread的参数

1.
/**
 * @describe 继承Thread类
 * @author lys
 * @date 2023/3/31
 */
    public class demo3 extends Thread{
    //private  int startIndex=1;
    private static  int startIndex=1;
    private final static int  MAX=50;
    private final String name;

    public demo3(String name) {
        this.name = name;
    }


    @Override
    public void run() {
        while (startIndex < MAX) {
            System.out.println(name+ "的号码" + (startIndex++));
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public static void main(String[] args) {

        demo3 demo3 = new demo3("1号窗口");
        demo3.start();
        demo3 demo31 = new demo3("2号窗口");
        demo31.start();
        demo3 demo32 = new demo3("3号窗口");
        demo32.start();

    }
    
2.
/**
 * @describe 实现Runnable接口
 * @author lys
 * @date 2023/3/31
 */
public class demo2 implements Runnable{
    private int startIndex=1;
    private final static int  MAX=50;
    @Override
    public void run() {
        while (startIndex<MAX){
            System.out.println(Thread.currentThread()+"的号码"+(startIndex++));
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

    }

    public static void main(String[] args) {

        demo2 demo2 = new demo2();
        Thread thread = new Thread(demo2,"1号窗口");
        Thread thread2 = new Thread(demo2,"2号窗口");
        Thread thread3 = new Thread(demo2,"3号窗口");
        thread.start();
        thread2.start();
        thread3.start();

    }
}

Runnable 接口的职责

只定义一个无参数,无返回值的 run方法

Runnable接口的run方法和Tread类的run方法的重要不同之处就是Tread类的run方法是不能共享的,A线程不能把B线程的run方法当做自己的执行单元,而Runnable接口很容易实现,可以使用相同的Runnable实例构造不同的Tread实例

/**
 * @author lys
 * @describe 实现Thread类
 * @date 2023/3/31
 */
public class demo3 extends Thread {
    private int startIndex = 1;
    //private static  int startIndex=1;
    private final static int MAX = 50;
    private final String name;

    public demo3(String name) {
        this.name = name;
    }


    @Override
    public void run() {
        while (startIndex < MAX) {
            System.out.println(name + "的号码" + (startIndex++));
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }


    public static void main(String[] args) {

        demo3 demo3 = new demo3("1号窗口");
        demo3.start();
        demo3 demo31 = new demo3("2号窗口");
        demo31.start();
        demo3 demo32 = new demo3("3号窗口");
        demo32.start();
    }


    
    
    

在这里插入图片描述


/**
 * @describe 实现Runnable接口
 * @author lys
 * @date 2023/3/31
 */
public class demo2 implements Runnable{
    private int startIndex=1;
    private final static int  MAX=50;
    @Override
    public void run() {
        while (startIndex<MAX){
            System.out.println(Thread.currentThread()+"的号码"+(startIndex++));
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

        }



    }

    public static void main(String[] args) {

        demo2 demo2 = new demo2();
        Thread thread = new Thread(demo2,"1号窗口");
        Thread thread2 = new Thread(demo2,"2号窗口");
        Thread thread3 = new Thread(demo2,"3号窗口");

        thread.start();
        thread2.start();
        thread3.start();

    }
}

在这里插入图片描述

策略设计模式

将控制本身和业务逻辑的运行分离开来,达到职责分明,功能单一的原则

Runnable就是抽象的策略接口,针对不同的策略,执行相对应的方法实现策略即可

多线程的使用

有效利用多线程的关键是理解程序是并发执行而不是串行执行的。例如:程序中有两个子系统需要并发执行,这时候就需要利用多线程编程。

策略设计模式

将控制本身和业务逻辑的运行分离开来,达到职责分明,功能单一的原则

Runnable就是抽象的策略接口,针对不同的策略,执行相对应的方法实现策略即可

多线程的使用

有效利用多线程的关键是理解程序是并发执行而不是串行执行的。例如:程序中有两个子系统需要并发执行,这时候就需要利用多线程编程。通过对多线程的使用,可以编写出非常高效的程序,例如:当你有多个无关联查询语句需要执行的时候,你就可以创建多个线程异步查询数据库,在所有异步线程执行完毕后,阻塞取出结果,而不用同步等待,尤其是当查询数据量较大的时候,会影响代码的执行效率

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雨落纠纷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值