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知识点看看就好了。也不难

目录
相关文章
|
2月前
|
设计模式 消息中间件 安全
【JUC】(3)常见的设计模式概念分析与多把锁使用场景!!理解线程状态转换条件!带你深入JUC!!文章全程笔记干货!!
JUC专栏第三篇,带你继续深入JUC! 本篇文章涵盖内容:保护性暂停、生产者与消费者、Park&unPark、线程转换条件、多把锁情况分析、可重入锁、顺序控制 笔记共享!!文章全程干货!
235 1
|
2月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
174 1
|
2月前
|
Java 编译器 Go
【Java】(5)方法的概念、方法的调用、方法重载、构造方法的创建
Java方法是语句的集合,它们在一起执行一个功能。方法是解决一类问题的步骤的有序组合方法包含于类或对象中方法在程序中被创建,在其他地方被引用方法的优点使程序变得更简短而清晰。有利于程序维护。可以提高程序开发的效率。提高了代码的重用性。方法的名字的第一个单词应以小写字母作为开头,后面的单词则用大写字母开头写,不使用连接符。例如:addPerson。这种就属于驼峰写法下划线可能出现在 JUnit 测试方法名称中用以分隔名称的逻辑组件。
202 4
|
2月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
198 1
|
3月前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案
Java 数据库 Spring
157 0
|
3月前
|
算法 Java
Java多线程编程:实现线程间数据共享机制
以上就是Java中几种主要处理多线程序列化资源以及协调各自独立运行但需相互配合以完成任务threads 的技术手段与策略。正确应用上述技术将大大增强你程序稳定性与效率同时也降低bug出现率因此深刻理解每项技术背后理论至关重要.
249 16
|
4月前
|
缓存 并行计算 安全
关于Java多线程详解
本文深入讲解Java多线程编程,涵盖基础概念、线程创建与管理、同步机制、并发工具类、线程池、线程安全集合、实战案例及常见问题解决方案,助你掌握高性能并发编程技巧,应对多线程开发中的挑战。
|
4月前
|
数据采集 存储 前端开发
Java爬虫性能优化:多线程抓取JSP动态数据实践
Java爬虫性能优化:多线程抓取JSP动态数据实践
|
5月前
|
存储 缓存 NoSQL
java 集合入门基础理论的核心概念与实用长尾知识
本文介绍了Java集合框架的基础理论知识,包括单列集合(List、Set、Queue)和双列集合(Map)的特点及常用实现类(如ArrayList、HashSet、HashMap等)。详细讲解了集合的遍历方式(迭代器、增强for循环、Lambda表达式)和典型应用场景(如数据去重、键值存储等)。通过具体代码示例,帮助初学者理解集合框架的核心概念和实际应用,为Java编程中的数据存储与管理提供基础指导。
147 0

热门文章

最新文章