java多线程_01

文章介绍了线程的基本概念,包括程序、进程和线程的差异,阐述了Java程序的运行原理,强调了多线程在并发和并行执行中的区别。接着详细讲解了Java中创建线程的三种方式:继承Thread类、实现Runnable接口和实现Callable接口。最后对各种线程创建方式的优缺点进行了总结。
摘要由CSDN通过智能技术生成

1. 线程的概念

多线程是所有应用程序中都非常重要的特性,在Java中也是相同,一般情况多线程仅用于网络编程,服务器程序开发,以及常见的UI底层开发,或者系统底层开发,所以一般只要涉及到多线程开发那么程序就会非常复杂,代码逻辑也非常复杂
多线程的作用就是让程序在执行任务期间key同事操作多个任务或多个线程操作一个任务,从而达到提高执行效率
多线程程序:

  1. 现实生活:一个人跟一堆小姐姐聊天
  2. 软件:QQ,微信,迅雷,音乐软件
1. 程序

程序是一个静态的概念(未开启时),程序一般是指计算机中的一个可执行文件,例如:QQ,微信,等软件,当双击时会将对应的应用程序加载到内存中,并且开始执行程序并产生进程,程序开启后会生成进程

2. 进程

进程是一个正在运行的程序,当双击某个程序时会在内存中加载运行,所以进程就是在内存运行的程序,进程是动态的概念,程序加载过程就是在内存中会产生一个进程,并具有一定的功能,同时操作系统中允许开启多个进程,进程的最小执行单元是线程,进程的执行前提是必须要有一个线程执行,否则会程序终止

3. 线程

线程进程中最小的执行单元,主要赋值程序的运行,一个进程中至少要有一个线程执行,如果没有线程则进程就无法执行,导致进程结束
一个进程中允许启动多个线程(多个功能或任务),线程分为多线程和单线程

  1. 单线程:进程中只有一个执行的线程,任务的执行必须是顺序执行,当一个任务执行完毕后下一个任务才可以继续执行(依次执行)
  2. 多线程:进程中有多个执行的线程,任务可以同事执行,并且任务间不会存在互相干扰,互相影响的问题
4. Java程序的运行原理

Java的运行是由命令启动Java虚拟机(JVM),JVM启动后就等于是开起来一个进程,进程的开启是由类中的main方法执行,main方法是Java程序主线程,所有逻辑代码都是在main方法执行的,一般main方法就是程序入口
Java是多线程还是单线程?
答案是多线程。原因是垃圾回收线程也要先启动,否则很容易会出现内存溢出。现在的垃圾回收线程加上前面的主线程,最低启动了两个线程,所以,JVM的启动其实是多线程的

5. 并发与并行概念
1. 并发

并发是指程序同一时间只能执行一条指令,多线程开启时会快速轮询切换(由CPU决定切换执行),从宏观上看是多个线程同时执行,但是在微观上并不是多个线程同时执行,而是将时间分为若干份,通过CPU切换执行(交替执行)
在同一个时间段内只能有一个线程执行,线程执行的途中其他线程则无法执行,这个是由CPU决定,三个线程不会出现同时执行的情况

2. 并行

并行是指程序同一时间可以执行多条指令,在同一个时限内宏观上看是同时执行,在微观上看也是同时执行,在一个时间片段内可以共同执行,这种效率也是最高
并行执行是在同一个时间片段内多条指令同时执行,同一个时间内三个线程可以同时执行并互不干扰
在这里插入图片描述

3. 并发编程和并行编程

并发编程与并行编程完全取决于CPU是否足够强大
如果CPU比较繁忙,资源不足时开启多个线程,那么是由CPU决定执行的线程应该是谁(多个线程抢夺CPU的执行权),谁抢夺到了谁执行,线程会尽可能抢夺执行权
如果CPU资源充足,那么开启多个线程或进程则可以分配不同的CPU内核(核心),此时多个进程中的多个线程则会同时执行,互不干扰,也不会出现抢夺CPU执行权的问题,每个线程都会分配独立的CPU内核运行
单核CPU最多只能并发编程,多核CPU可以实现并行编程

在这里插入图片描述
一个物理cpu(计算机主板上实际安装的cpu)可以有多个核心数,简称多核cpu;单核cpu是指一个cpu只有一个处理核心,双核cpu是指一个cpu具有两个处理核心,多核cpu是指一个cpu具有多个核心;计算机主板上可以安装多个物理cpu。

物理cpu内核总数=物理cpu数*每颗物理cpu核心数

逻辑cpu总数=总的物理cpu内核数*超线程数

这个电脑是六核十二线程,即一个物理cpu具有六个核心数属于多核cpu。

真正实现多线程效果的是:start0(),而不是run()方法,,很可惜的是start0()方法是本地方法由native关键字修饰,该方法由JVM调用,方法底层是由C/C++实现。

2. Java中的Thread线程类

Java中的线程启动需要使用Thread类的方法,此类用于创建并启动线程,其中定义了很多的构造方法与启动线程的方法,用于启动线程和定义线程规则等功能,同时还提供了静态获取方法以及普通获取方法,Thread类位于java.lang核心包中,所以不需要导包

1. Thread类构造方法
  1. public Thread():创建线程类对象
  2. public Thread(String name):创建线程类对象,并指定线程名称
  3. public Thread(Runnable target):创建线程类对象,并指定Runnable实现类
  4. public Thread(Runnable target, String name):创建线程类对象,并指定Runnable实现类以及指定线程名称
  5. public Thread(ThreadGroup group, String name):创建线程类对象,并指定线程分组以及指定线程名称
  6. public Thread(ThreadGroup group, Runnable target):创建线程类对象,并指定线程分组以及指定Runnable实现类
  7. public Thread(ThreadGroup group, Runnable target, String name):创建线程类对象,并指定线程分组以及指定Runnable实现类和指定线程名称
2. Thread类普通方法
  1. public long getId():获取当前线程对象ID
  2. public final String getName():获取当前线程对象名称
  3. public final int getPriority():获取当前线程优先级别
  4. public State getState():获取当前线程状态
  5. public final ThreadGroup getThreadGroup():获取当前线程分组
3. Thread类静态方法
  1. public static native Thread currentThread():获取当前正在执行的线程对象
4. Thread类特殊方法
  1. public void run():用于编写线程任务的方法(多线程执行的任务方法),继承后必须自定义实现的方法
  2. public synchronized void start():启动线程方法,当调用start方法时此方法会有JVM虚拟机调用执行run方法中的任务代码

3.线程的创建方式

1. 继承Thread类

创建一个类并继承Thread类,并重写run方法,在run方法中实现自己的线程任务,同时可以创建构造方法,调用父类的构造方法实现设置线程的信息

/**
 * 多线程创建方式一:继承Thread类重写run方法
 */
class CreateMethod1 extends Thread{

    public CreateMethod1(){}
    public CreateMethod1(String name){
        super(name);
    }
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("createMethod1:"+i);
        }
    }
}
public class ThreadTest {

    public static void main(String[] args) {
        CreateMethod1 createMethod1 = new CreateMethod1("这个女生");
        createMethod1.start();
        System.out.println(createMethod1.getName());
        System.out.println("ID:"+createMethod1.getId());
        System.out.println("优先级别:"+createMethod1.getPriority());
        System.out.println("当前线程:"+Thread.currentThread());
        for (int i = 10; i < 20; i++) {
            System.out.println("threadTest:"+i);
        }
    }
}
2. 实现Runnable接口

创建一个类实现Runnable接口,并重写run方法,run方法就是线程任务方法

//实现Runnable接口重写run方法
class CreateMethod2 implements Runnable{
    @Override
    public void run() {
        Thread thread = Thread.currentThread();
        System.out.println("次线程名称:"+thread.getName());
        System.out.println("次线程状态:"+thread.getState());
        System.out.println("次线程优先级:"+thread.getPriority());
        for (int i = 0; i < 10; i++) {
            System.out.println("实现Runnable接口:"+i);
        }
    }
}
public class ThreadTest2 {
    public static void main(String[] args) {
        CreateMethod2 createMethod2 = new CreateMethod2();
        Thread t1 = new Thread(createMethod2, "实现Runnable接口");
        t1.start();
        for (int i = 40; i < 50; i++) {
            System.out.println("主线程:"+i);
        }
    }
}
3. 实现Callable接口

创建一个类实现Callable接口,并重写call方法,call方法就是线程任务类,启动线程还需要创建一个任务FutureTask类,再创建Thread类启动线程
Callable接口的call方法具有返回值并且可以声明异常,call方法的返回值由FutureTask获取

class CreateMethod3 implements Callable<String> {
    @Override
    public String call() throws Exception {
        Thread thread = Thread.currentThread();
        System.out.println("次线程名称:"+thread.getName());
        System.out.println("次线程状态:"+thread.getState());
        System.out.println("次线程优先级:"+thread.getPriority());
        // 任务代码
        // 循环10次
        for (int i = 1; i <= 10; i++) {
            System.out.println("次线程执行..." + i);
        }
        // 返回值
        return "线程执行完毕";
    }
}
public class ThreadTest3 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 1. 创建Callable实现类
        Callable threadTest3 = new CreateMethod3();
        // 2. 创建FutureTask类
        FutureTask<String> futureTask = new FutureTask<>(threadTest3);
        // 3. 创建Thread类
        Thread thread = new Thread(futureTask,"创建线程方式3");
        // 接收返回值,get()方法用于接收Callable接口的返回值
        // 调用此方法时必须时线程已被启动的,如果是未启动则会造成程序阻塞等待
        // get方法调用后会等待接收返回值,等待途中其他代码不会执行
        thread.start();
        String res = futureTask.get();
        System.out.println("result = " + res);
        for (int i = 50; i < 60; i++) {
            System.out.println("主线程:"+i);
        }
    }
}

4. 多线程创建方式总结
  1. 继承Thread类
    1. 优点:实现简单
    2. 缺点:无返回值,异常不能声明抛出,Java是单继承,一旦继承Thread类则无法继承其他类
  2. 实现Runnable接口–>常用
    1. 优点:解决了单继承的问题,实现相对较为简单
    2. 缺点:无返回值,异常不能声明抛出
  3. 实现Callable接口
    1. 优点:解决了单继承问题,有返回值,异常可以声明抛出
    2. 缺点:实现较为复杂,接收返回值会造成程序阻塞,等待接收返回值,接收返回值后才可以继续执行
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值