JAVA多线程详解(超详细)-程序员宅基地

技术标签: 面试  python  java  阿里巴巴资料职业发展  后端  学习路线  开发语言  

目录

一、线程简介

1、进程、线程

  • 程序:开发写的代码称之为程序。程序就是一堆代码,一组数据和指令集,是一个静态的概念。
  • 进程(Process):将程序运行起来,我们称之为进程。进程是执行程序的一次执行过程,它是动态的概念。进程存在生命周期,也就是说程序随着程序的终止而销毁。进程之间是通过TCP/IP端口实现交互的。
  • 线程(Thread):线程是进程中的实际运作的单位,是进程的一条流水线,是程序的实际执行者,是最小的执行单位。通常在一个进程中可以包含若干个线程,当然一个进程中至少有一个线程。线程是CPU调度和执行的最小单位。
    注意:很多多线程都是模拟出来的,真正的多线程是指有多个CPU,即多核,如服务器,如果是模拟出来的多线程,即一个CPU的情况下,在同一个时间点,CPU只能执行一个代码,因为切换的很快,所以就有同时执行的错觉。

2、并发、并行、串行

  • 并发:同一个对象被多个线程同时操作。(这是一种假并行。即一个CPU的情况下,在同一个时间点,CPU只能执行一个代码,因为切换的很快,所以就有同时执行的错觉)。
  • 并行:多个任务同时进行。并行必须有多核才能实现,否则只能是并发。
  • 串行:一个程序处理完当前进程,按照顺序接着处理下一个进程,一个接着一个进行。

3、进程的三态

进程在运行的过程中不断的改变其运行状态。通常一个运行的进程必须有三个状态,就绪态、运行态、阻塞态。

  • 就绪态:当进程获取出CPU外所有的资源后,只要再获得CPU就能执行程序,这时的状态叫做就绪态。在一个系统中处于就绪态的进程会有多个,通常把这些排成一个队列,这个就叫就绪队列。
  • 运行态:当进程已获得CPU操作权限,正在运行,这个时间就是运行态。在单核系统中,同一个时间只能有一个运行态,多核系统中,会有多个运行态。
  • 阻塞态:正在执行的进程,等待某个事件而无法继续运行时,便被系统剥夺了CPU的操作权限,这时就是阻塞态。引起阻塞的原因有很多,比如:等待I/O操作、被更高的优先级的进程剥夺了CPU权限等。

二、线程实现

1、继承Thread类

 步骤:
 - 自定义线程类继承Thread类
 - 重写run()方法,编写线程执行体
 - 创建线程对象,调用start()方法启动线程(启动后不一定立即执行,抢到CPU资源才能执行)

代码如下(示例):

// 自定义线程对象,继承Thread,重写run()方法
public class MyThread extends Thread {

    public MyThread(String name){
        super(name);
    }

    @Override
    public void run() {
        // 线程执行体
        for (int i = 0; i < 10; i++) {
            System.out.println("我是自定义" + Thread.currentThread().getName() + "--" + i);
        }
    }

    public static void main(String[] args) {
        // main线程,主线程

        // 创建线程实现类对象
        MyThread thread = new MyThread("线程1");
        MyThread thread2 = new MyThread("线程2");
        // 调用start()方法启动线程
        thread.start();
        thread2.start();

        for (int i = 0; i < 10; i++) {
            System.out.println("我是主线程--" + i);
        }
    }
}


执行结果:


我是自定义线程2--0
我是自定义线程2--1
我是主线程--0
我是自定义线程1--0
我是主线程--1
我是主线程--2
我是自定义线程2--2
我是主线程--3
我是自定义线程1--1
我是主线程--4
我是主线程--5
我是主线程--6
我是主线程--7
我是主线程--8
我是主线程--9
我是自定义线程2--3
我是自定义线程1--2
我是自定义线程2--4
我是自定义线程1--3
我是自定义线程1--4
我是自定义线程1--5
我是自定义线程1--6
我是自定义线程1--7
我是自定义线程1--8
我是自定义线程1--9
我是自定义线程2--5
我是自定义线程2--6
我是自定义线程2--7
我是自定义线程2--8
我是自定义线程2--9

2、实现Runnable接口

 步骤:
 - 自定义线程类实现Runnable接口
 - 实现run()方法,编写线程体
 - 创建线程对象,调用start()方法启动线程(启动后不一定立即执行,抢到CPU资源才能执行)

代码如下(示例):

// 自定义线程对象,实现Runnable接口,重写run()方法
public class MyRunnable implements Runnable {
    @Override
    public void run() {
        // 线程执行体
        for (int i = 0; i < 10; i++) {
            System.out.println("我是自定义" + Thread.currentThread().getName() + "--" + i);
        }
    }

    public static void main(String[] args) {
        // main线程,主线程

        // 创建实现类对象
        MyRunnable myRunnable = new MyRunnable();
        // 创建代理类对象
        Thread thread = new Thread(myRunnable,"线程1");
        Thread thread2 = new Thread(myRunnable,"线程2");
        // 调用start()方法启动线程
        thread.start();
        thread2.start();

        for (int i = 0; i < 10; i++) {
            System.out.println("我是主线程--" + i);
        }
    }
}

执行结果:

我是主线程--0
我是自定义线程1--0
我是自定义线程2--0
我是自定义线程1--1
我是主线程--1
我是自定义线程1--2
我是自定义线程2--1
我是自定义线程1--3
我是主线程--2
我是主线程--3
我是自定义线程1--4
我是自定义线程2--2
我是自定义线程2--3
我是自定义线程2--4
我是自定义线程1--5
我是自定义线程1--6
我是主线程--4
我是自定义线程1--7
我是自定义线程1--8
我是自定义线程1--9
我是自定义线程2--5
我是自定义线程2--6
我是自定义线程2--7
我是自定义线程2--8
我是主线程--5
我是自定义线程2--9
我是主线程--6
我是主线程--7
我是主线程--8
我是主线程--9

3、实现Callable接口(不常用)

 步骤:
 - 实现Callable接口,先要返回值类型
 - 重写call()方法,需要抛出异常
 - 创建目标对象
 - 创建执行服务:ExecutorService ser = Executor.newFixedThreadPool(1);
 - 提交执行:Future<Boolean> res = ser.submit(t1);
 - 获取结果:boolean r1 = res.get();
 - 关闭服务:ser.shutdownNow();

代码如下(示例):

import java.util.concurrent.*;

// 自定义线程对象,实现Callable接口,重写call()方法
public class MyThread implements Callable<Boolean> {

    @Override
    public Boolean call() throws Exception {
        // 线程执行体
        for (int i = 0; i < 10; i++) {
            System.out.println("我是自定义" + Thread.currentThread().getName() + "--" + i);
        }

        return true;
    }

    public static void main(String[] args) throws ExecutionException,
        InterruptedException {
        // main线程,主线程

        // 创建线程实现类对象
        MyThread thread = new MyThread();
        MyThread thread2 = new MyThread();

        // 创建执行服务,参数是线程池线程数量
        ExecutorService ser = Executors.newFixedThreadPool(2);
        // 提交执行
        Future<Boolean> res = ser.submit(thread);
        Future<Boolean> res2 = ser.submit(thread2);
        // 获取结果
        boolean r1 = res.get();
        boolean r2 = res2.get();
        // 关闭服务
        ser.shutdownNow();
    }
}


执行结果:


我是自定义pool-1-thread-1--0
我是自定义pool-1-thread-2--0
我是自定义pool-1-thread-1--1
我是自定义pool-1-thread-1--2
我是自定义pool-1-thread-1--3
我是自定义pool-1-thread-1--4
我是自定义pool-1-thread-1--5
我是自定义pool-1-thread-2--1
我是自定义pool-1-thread-1--6
我是自定义pool-1-thread-2--2
我是自定义pool-1-thread-2--3
我是自定义pool-1-thread-2--4
我是自定义pool-1-thread-2--5
我是自定义pool-1-thread-2--6
我是自定义pool-1-thread-2--7
我是自定义pool-1-thread-2--8
我是自定义pool-1-thread-2--9
我是自定义pool-1-thread-1--7
我是自定义pool-1-thread-1--8
我是自定义pool-1-thread-1--9

三、线程常用方法

1、线程的状态

  • 新建状态(NEW):线程已创建,尚未调用start()方法启动之前。
  • 运行状态(RUNNABLE):线程对象被创建后,调用该对象的start()方法,并获取CPU权限进行执行。
  • 阻塞状态(BLOCKED):线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态。
  • 等待状态(WAITING ):等待状态。正在等待另一个线程执行特定动作来唤醒该线程的状态。
  • 超时等待状态(TIME_WAITING):有明确结束时
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_74823434/article/details/133744388

智能推荐

关于UE4通过python获取静态网格体插槽的问题_python ue4模型获取材质插槽-程序员宅基地

文章浏览阅读899次。之前做项目可以很轻松的获取skeletal mesh的材质插槽,但是静态mesh没有同样的功能。于是在google 搜到了一个答案,在此记录一下:Ok, so the function get_material_slot_names() is a method of the StaticMeshComponent class. So you are able to retrieve the materials from base StaticMesh class by first creating a _python ue4模型获取材质插槽

基于网络的入侵检测数据集研究综述(A Survey of Network-based Intrusion Detection Data Sets)-程序员宅基地

摘要:该综述论文对基于网络的入侵检测数据集进行了分析和总结,强调了标记数据在训练和评估入侵检测系统中的重要性。文章建议用户在多个数据集上进行评估,避免过度拟合和人为影响,并提倡使用标准格式的数据集和预定义的训练和测试子集。总的来说,虽然没有完美的数据集,但有许多好的数据集可供使用,社区可以通过更密切的合作从中受益。

centos部署http代理+解决国内服务器TGbot_tg内置代理账号密码-程序员宅基地

文章浏览阅读2.9k次。使用tgbot需要代理才能使用,参考各路大神,把适合自己的方法总结如下,本人小白,大佬勿喷:首先,先把带密码的http代理的使用方法写上http://账号:密码@ip:port部署安装openssl判断是否安装opensslopenssl version -a安装命令yum install openssl安装squidyum install squid -y# -y 代表自动选择y,全自动安装安装net-toolsyum install net-tools修改squi_tg内置代理账号密码

正则匹配相邻n个重复字符_正则匹配多个字符串重复n次-程序员宅基地

文章浏览阅读1.9k次。正则匹配相邻n个重复字符//var reg = /([0-9a-zA-Z])\1{n-1}/;var reg = /([0-9a-zA-Z])\1{2}/;reg.test('2333');//true_正则匹配多个字符串重复n次

哨兵2号(Sentinel2)卫星数据处理_哨兵二号数据处理-程序员宅基地

文章浏览阅读3.9w次,点赞13次,收藏150次。李国春哨兵2号数据是一个重要的共享免费数据源,原来我就知道这个数据的应用很受重视,可是没想到现在在国内是如此空前的重视。哨兵数据处理人家ESA有自己的SNAP处理软件,非常好的软件。RSD也来凑凑热闹,也加了处理哨兵2号卫星数据的功能。介绍RSD处理哨兵数据之前先夸夸这数据,数据质量真好。但是最让我感动的还是人家的元数据,写的那是真好啊,看来值得我们学习的东西还有很多。好了,言归正传。..._哨兵二号数据处理

org.json.simple 使用详解-程序员宅基地

文章浏览阅读467次。一、概览JSON.simple是一个很简单的JSON处理,读取和写JSON数据的JAVA库,它完全兼容JSON的标准(RFC4627).你可以用JSON.simple来编码或解码JSON文本。【NOTE】如果想将对象转换成JOSN,或将JSON转换成对象,你需要考虑使用Jackson或Gson。二、功能JSON.simple的功能:. 完全兼容JSON的标准(RFC4627). ..._org.json.simple

随便推点

matlab 三维曲线投影怎么画-程序员宅基地

文章浏览阅读1.9k次,点赞2次,收藏3次。Matlab 提供了许多用于绘制三维曲线的函数。你可以使用 plot3 函数绘制三维曲线,并使用 view 函数来调整视图,使得曲线投影在平面上。以下是一个示例代码:t = 0:0.1:10;x = sin(t);y = cos(t);z = t;plot3(x, y, z)view(-35, 45)这将绘制一条三维曲线,并使用视角为 -35 度在 x-y 平面上投影,以 45 ..._matlab三维图投影到指定平面

stc8h单片机利用websocket协议通过esp8266将数据传输到服务器_esp8266连接websocket指令-程序员宅基地

文章浏览阅读333次。在STC8H单片机上使用WebSocket协议通过ESP8266传输数据到WebSocket服务器,然后接收和解析服务器下发的数据,涉及到嵌入式开发、网络通信以及WebSocket协议的使用。:ESP8266是一个低成本的Wi-Fi模块,它可以将STC8H采集的数据封装成WebSocket消息并通过Wi-Fi网络传输到WebSocket服务器。:WebSocket服务器是一个网络服务器,它能够接收来自ESP8266的WebSocket消息,处理它们,并向连接的设备发送WebSocket消息。_esp8266连接websocket指令

软件开发毕业4年后,靠自学自动化测试月入2W,本人亲身经历供大家参考_自学了自动化测试,但是没有实际做过项目怎么办-程序员宅基地

文章浏览阅读1.6k次。大专毕业4年了,靠自学自动化测试月入2万,本人亲身经历供大家参考。毕业院校:湖南科技职业学院软件开发与应用专业。学校课程很杂,都只教点皮毛,是真正的师傅领进门,修行在个人,在学校我也不是优生。(附带银行流水)读书那会我在校门口网吧做网管夜班兼职,晚上事情少,有大把时间玩游戏,其实我最初自学Python是因为我玩游戏想做WG(游戏辅助软件)刷某些游戏里的东西换钱_自学了自动化测试,但是没有实际做过项目怎么办

javascript中关于onbeforeunload事件,页面无法弹出会话框的处理方法_window.onbeforeunload alert没弹窗-程序员宅基地

文章浏览阅读1.8k次。从2011年5月25日起,HTML5 规范声明:onbeforeunload事件的处理函数中调用下列弹窗相关的方法时,可以忽略不执行,window.showModalDialog(),window.alert(),window.confirm()window.prompt().上面的那句话,引用于:https://developer.mozilla.org/zh-CN/docs/We..._window.onbeforeunload alert没弹窗

Ubuntu 下安装 MySQL Workbench-程序员宅基地

文章浏览阅读97次。打开终端输入命令:sudo dpkg -i mysql-workbench-community-6.0.9-1ubu1204-i386.deb如果安装不成功的提示,可以输入以下命令:apt-get -f install然后重新输入命令sudo dpkg -i mysql-workbench-community-6.0.9-1ubu1204-i386.deb安装..._qgis : 依赖: libgdal.so.1-1.11.3 但无法安装它 依赖: libgdal1i (>= 1.8.0) 但

自学 unity 3D 界面翻译_unity中文界面翻译-程序员宅基地

文章浏览阅读686次。翻译_unity中文界面翻译

推荐文章

热门文章

相关标签