java多线程之概念和3种创建方式(详解)

简介: 进程:一个执行的应用程序线程:一个应用程序内的具体执行不同模块

一、概念讲解

1.进程和线程的概念

进程:一个执行的应用程序

线程:一个应用程序内的具体执行不同模块

2.进程和进程之间的关系

进程和进程内存独立不共享

3.线程和线程之间的关系

(1)Java中至少有两个线程并发,一个是垃圾回收线程,一个是执行main方法的主线程

(2) 一个线程一个栈(每个栈之间独立执行,互不干扰,即多线程并发),栈内存独立堆内存和方法区内存共享

(3)多线程的目的:提高程序的处理效率

(4)单核CPU能做到多线程并发吗:不能(cpu切换处理很快,超过肉眼速度,给人能多线程的假象)

4.并发和并行的概念

并发:一个cpu去执行不同的线程任务(哪里有任务就去哪里执行)

并行:许多个cpu一起去执行不同线程任务(对一个cpu说,好兄弟,我们一起来齐心协力干吧)

5.线程对象的生命周期:

(1)新建状态(new):

程序使用new关键字创建了一个进程后,该线程就是新建状态,内存由JVM分配,并初始化成员变量的值。

(2)就绪状态(runnable):

线程对象调用start方法后,该线程就变成了就绪状态 ,JVM会为其创建方法栈和程序计数器,等待调度运行。

(3)运行状态(running)

处于就绪的线程获得了cpu,开始执行run方法的线程

(4)阻塞状态(blocked)

线程因为某种原因放弃了cpu的使用权,暂停运行,直到线程通过就绪状态再进入运行状态。阻塞的情况有三种。

(4.1)等待阻塞(o.wait):等待队列。运行的线程执行o.wait方法,JVM会把该线程放入等待队列

(4.2)同步阻塞(lock):锁池。运行的线程在获取对象的同步锁时,若该同步锁被其他线程占用,JVM会把该线程放入锁池中

(4.3)其他阻塞(sleep/join):运行的线程执行sleep、join或者IO请求时,JVM会把该线程设为阻塞状态。当sleep、join等待线程超时或终止或者IO处理完毕时,该线程重新进入就绪状态。

(5)线程死亡(dead)

线程结束就是死亡状态。线程死亡分为三种

(5.1)正常结束:run或call方法执行完成

(5.2)异常结束:线程抛出一个未捕获的Exception或者Error

(5.3)强制结束:通过调用stop方法来结束线程,容易导致线程进入死锁,不推荐使用

二、创建线程的方式

方式一:编写一个类,继承java.lang.Thread

优缺点:

优点:编码简单

缺点:继承存在单继承的局限性,线程类继承Thread后,不能继承其他类,不利于扩展

步骤:

1.main方法外定义一个子线程继承Thread类。

2.重写run方法。(线程具体要执行的事情写在run方法里面)

3.new出一个Thread子线程对象-----要在main方法里面。(子线程要写在主线程方法之前)

4.调用start方法启动线程(调用这个才代表多线程启动,调用run只是单线程)

代码例子:

package bao;
public class Test {
    public static void main(String[] args) {
        //4.创建Thread子线程的对象(要创建在主线程之前,要不然失去了多线程的意义)
        Thread t = new MyThread();
        //5.启动线程(执行的是run方法)
        t.start();
        //6.创建一个main方法里面的主线程进行比较
        for (int i = 0; i < 5; i++) {
            System.out.println("主线程执行输出:"+i);
        }
    }
}
    //1.定义一个子线程继承Thread类
    class MyThread extends Thread{
    //2.重写run方法:在里面定义子线程要做什么   快捷键:run+回车键
        @Override
        public void run() {
            super.run();
    //3.子线程要做的事情  例子:要看执行循环多少次
            for (int i = 0; i < 5; i++) {
                System.out.println("子线程执行输出:"+i);
            }
        }
    }

运行结果:

子线程执行输出:0

主线程执行输出:0

子线程执行输出:1

主线程执行输出:1

子线程执行输出:2

主线程执行输出:2

子线程执行输出:3

主线程执行输出:3

子线程执行输出:4

主线程执行输出:4

方式二: 编写一个类,实现java.lang.Runnable接口

优缺点:

优点:线程任务类只是实现接口,还可以继续继承类和实现接口,可扩展性强,容易实现资源共享

缺点:编程多一层对象包装,如果线程有执行结果是不能直接返回的

步骤:

1.main方法外定义一个子线程MyRunnable实现Runnable接口

2.重写run方法。(线程具体要执行的事情写在run方法里面)

3.new出一个MyRunnable对象(然后传给Thread对象)

4.new出一个Thread子线程对象-----要在main方法里面。(子线程要写在主线程方法之前)

5.调用start方法启动线程(调用这个才代表多线程启动,调用run只是单线程)

ps:这个创建线程方法和第一个创建线程方法就第一步不一样。还有在new子对象出来之前要创建一个MyRunnable对象,把这个值传入子线程对象里面。其他的都一样步骤

代码例子:

package bao;
public class Test {
    public static void main(String[] args) {
        //4.创建MyRunnable对象,并传给Thread子线程
        Runnable target = new MyRunnable();
        //5.创建Thread子线程对象
        Thread t = new Thread(target);
        //6.启动线程
        t.start();
        //7.创建一个main方法里面的主线程进行比较
        for (int i = 0; i < 5; i++) {
            System.out.println("主线程输出:"+i);
        }
    }
}
//1.定义一个线程类,实现Runnable接口
class MyRunnable implements Runnable{
//2.重写run方法。run方法里面定义线程要执行的代码。快捷键:run+回车键
    @Override
    public void run() {
//3.定义线程要执行的任务
        for (int i = 0; i < 5; i++) {
            System.out.println("子线程输出:"+i);
        }
    }
}

运行结果:

子线程输出:0

子线程输出:1

主线程输出:0

子线程输出:2

主线程输出:1

子线程输出:3

主线程输出:2

子线程输出:4

主线程输出:3

主线程输出:4

方式三: 编写一个类,实现Callable接口

优缺点:

优点: 在方式二的优点上,还能获取线程执行结果(上面两个就不能)

缺点:编程麻烦

步骤:

1.定义一个MyCallable线程类,实现Callable接口

2.重写Call方法(线程具体要执行的事情写在Call方法里面)

3.创建MyCallable任务对象,值交给下一步

4.创建FutureTask,值交给下一步

5.创建Thread线程对象

6.调用start方法启动线程

7.get方法输出线程执行结果

代码例子:

package bao;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Test {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //4.创建MyCallable任务对象,值交给下一步
        Callable<String> call = new MyCallable(100);
        //5.创建FutureTask,值交给下一步
        FutureTask<String> f1 = new FutureTask<>(call);
        //6.创建Thread线程对象
        Thread t = new Thread(f1);
        //7.启动线程
        t.start();
        //输出结果
        System.out.println(f1.get());//遇到异常抛出或者捕捉处理就好了
    }
}
//1.定义一个MyCallable线程类,实现Callable接口
class MyCallable implements Callable<String>{  //填写String就返回类型结果
    //3.2写在这里方便阅读
    private int n;
    public MyCallable(int n) {
        this.n=n;
    }
    //2.重写Call方法,并在里面写子线程要执行的任务  快捷键:call+回车键
    @Override
    public String call() throws Exception {
        //return null;   需要返回值这个就要注释掉
//3.1定义线程要执行的任务  例子为求和
        int sum = 0;
        for (int i = 0; i < n; i++) {
            sum += i;
        }
        return "子线程的执行结果为"+sum;
    }
}

运行结果:

子线程的执行结果为4950

三、常用API(其实也不常用)

1.给线程改名字,为了方便区分线程。

作用:为了更加方便看到是哪个线程在执行

代码例子来自方式一的代码,拿来修改添加

详解:

1.按照这个格式输入

2.这个位置生成name的有参构造器

3.输入线程的名字

运行结果:(输出的基数大了才能看到主子线程交叉运行,比如500)

主线程执行:0

主线程执行:1

主线程执行:2

主线程执行:3

主线程执行:4

子线程:0

子线程:1

子线程:2

子线程:3

子线程:4

2.线程睡眠(延迟执行)

作用:延迟线程的执行结果

代码例子来自方式一的代码,拿来修改添加

运行结果:

子线程输出后,延迟了5秒后才执行主线程

旁白:掌握第一种创建方式,后面的那两种方式也差不多,就是改变接口和创建线程对象之前加了1层或者2层对象而已。还有重写的方法不一样,其他的都一样。根据不同的场景来用。常用的API知识点看看就好了。也不难

目录
相关文章
|
3天前
|
存储 缓存 前端开发
Java串口通信技术探究3:RXTX库线程 优化系统性能的SerialPortEventListener类
Java串口通信技术探究3:RXTX库线程 优化系统性能的SerialPortEventListener类
14 3
|
3天前
|
Java
JAVA难点包括异常处理、多线程、泛型和反射,以及复杂的分布式系统知识
JAVA难点包括异常处理、多线程、泛型和反射,以及复杂的分布式系统知识。入坑JAVA因它的面向对象特性、平台无关性、强大的标准库和活跃的社区支持。
14 2
|
3天前
|
Java 调度 开发者
Java中的多线程编程:基础与实践
【5月更文挑战第2天】本文将深入探讨Java中的多线程编程,从基础概念到实际应用,为读者提供全面的理解和实践指导。我们将首先介绍线程的基本概念和重要性,然后详细解析Java中实现多线程的两种主要方式:继承Thread类和实现Runnable接口。接着,我们将探讨线程同步的问题,包括synchronized关键字和Lock接口的使用。最后,我们将通过一个实际的生产者-消费者模型来演示多线程编程的实践应用。
|
3天前
|
安全 Java 程序员
Java中的多线程编程:从理论到实践
【5月更文挑战第2天】 在计算机科学中,多线程编程是一项重要的技术,它允许多个任务在同一时间段内并发执行。在Java中,多线程编程是通过创建并管理线程来实现的。本文将深入探讨Java中的多线程编程,包括线程的概念、如何创建和管理线程、以及多线程编程的一些常见问题和解决方案。
12 1
|
4天前
|
存储 安全 Java
深入理解Java并发编程:线程安全与性能优化
【5月更文挑战第1天】本文将深入探讨Java并发编程的核心概念,包括线程安全和性能优化。我们将详细分析线程安全问题的根源,以及如何通过合理的设计和编码实践来避免常见的并发问题。同时,我们还将探讨如何在保证线程安全的前提下,提高程序的并发性能,包括使用高效的同步机制、减少锁的竞争以及利用现代硬件的并行能力等技术手段。
|
4天前
|
并行计算 Java 数据处理
Java中的多线程编程:基础知识与实践
【5月更文挑战第1天】本文将深入探讨Java中的多线程编程,包括其基本概念、实现方式以及实际应用。我们将从理论和实践两个角度出发,详细解析线程的创建、启动、控制以及同步等关键问题,并通过实例代码演示如何在Java中有效地使用多线程。
|
4天前
|
Java 程序员
Java中的多线程编程:从理论到实践
【5月更文挑战第1天】 在现代计算机科学中,多线程编程是一个重要的概念,它允许程序员在同一程序中并行运行多个任务。Java作为一种广泛使用的编程语言,提供了一套丰富的多线程编程工具。本文将介绍Java中多线程编程的基本概念,包括线程的创建、启动、控制和同步,以及一些常见的多线程问题和解决方案。
|
4天前
|
存储 Java 程序员
Java中的多线程编程:基础知识与实践
【5月更文挑战第1天】在现代计算机科学中,多线程是一种重要的并行计算技术,允许多个执行流程并发运行。本文将深入探讨Java语言中的多线程编程,从基础概念到实际应用,帮助读者理解多线程的核心原理,并通过实例学习如何在Java中创建和管理线程。我们将涵盖线程的生命周期、同步机制以及如何利用高级类如Executor框架来优化多线程应用的性能。通过本文的学习,读者将具备设计和实现高效、稳定多线程Java应用程序的能力。
6 2
|
5天前
|
缓存 Java 调度
Java并发编程:深入理解线程池
【4月更文挑战第30天】 在Java并发编程中,线程池是一种重要的工具,它可以帮助我们有效地管理线程,提高系统性能。本文将深入探讨Java线程池的工作原理,如何使用它,以及如何根据实际需求选择合适的线程池策略。
|
2月前
|
安全 Java
深入理解Java并发编程:线程安全与性能优化
【2月更文挑战第22天】在Java并发编程中,线程安全和性能优化是两个重要的主题。本文将深入探讨这两个主题,包括线程安全的基本概念,如何实现线程安全,以及如何在保证线程安全的同时进行性能优化。
16 0