0

0

什么是进程与线程?

零下一度

零下一度

发布时间:2017-06-25 10:18:25

|

2098人浏览过

|

来源于php中文网

原创

一 概述

1.什么是进程?

进程是一个相对独立的执行单位。

2.什么是线程?

进程的一部分,进程中实际的任务执行者,必须依附于进程。线程对进程的依赖主要体现在:

  • 线程不能脱离进程开启,必须在进程开启的前提下开启。

  • 线程有时必须从进程中获取数据。

3.线程与进程的区别?

线程与进程是两个相对的概念,一个对象相对于它拥有的执行单位被称为进程,从自身所属的上级执行者来看,又被称作线程。

4.多线程的设计目的、用途、意义

CUP在任何一个时间点都只能执行一个线程,多线程的本质是多个任务高速交替执行。如果多个线程间不存在数据交换,可以单独执行,采用多线程并不能减少总的执行时间。

多线程设计的主要目的不是为了提高执行速度,而是相对平均地执行每一个线程,不致使某一个线程长时间持有CPU时间片,其他线程长时间处于等待状态。由于CPU时间片在多个线程间切换迅速,超出了人类感官所能察觉的范围,所以感觉多个任务都是执行。

例如,当多个人访问同一个网站,每一个人都需要5分钟,如果不采用多线程,同时只允许一个人进入网站,其他多数人都要等待5分钟,用户体验很差。这是采用多线程,一个人进入以后,CPU转向其他用户,让其他用户陆续进入,用户体验就提高了,尽管总的执行时间并没有减少。

5.CPU调度模式

  • 分时调度模式:系统平均地为各个线程分配CPU时间片。

  • 抢占式调度模式:各个线程抢夺CPU时间片,CPU时间片在线程间不均匀分配。

二 线程创建

1.Java SE API 提供了两种创建线程的方式:

  • 实现Runnable接口,将实现类的对象作为参数传入Thread的构造器中。

  • 直接继承Thread类。

2.无论采用哪种方式,需要执行的任务都必须放在run方法中。

3.两种创建方式的区别:

⑴Java采用单继承,即一个类只能继承一个父类,而允许一个类实现多个接口,采用继承Thread的方式创建线程,就使本类失去了唯一的一次继承机会。

⑵实现资源共享的方式不同

  • 首先需要明确的一点,通过继承Thread创建线程的方式也可以实现资源共享,只是由于通过new关键字创建的多个线程是不同的对象,那么共享资源只能来自于外部,通常通过构造器注入。

  • 而通过实现Runnable接口的方式创建线程,可以利用同一个实现类对象创建多个线程,实现了资源共享,共享资源来自线程内部。

4.采用实现Runnable接口的方式创建线程,不仅保留了唯一的继承机会,而且在实现资源共享的操作相对简单,所以一般采用该方式创建线程。

5.通过继承Thread的方式实现资源共享:

提供共享资源的外部类

package com.test.thread.extendsThread;public class MyClass {public int count;

}

Thread线程子类

package com.test.thread.extendsThread;public class MyThread extends Thread {private MyClass obj;public MyThread() {super();
    }public MyThread(MyClass obj) {super();this.obj = obj;
    }

    @Overridepublic void run() {
        System.out.println("obj=" + obj);while (true) {synchronized (obj) {if (obj.count > 0) {try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "----当前数量=" + obj.count--);
                } elsereturn;
            }
        }

    }

}

测试类

package com.test.thread.extendsThread;import org.junit.Test;import com.test.thread.synchronizedTest.demo02.MyTestRunnable;import net.sourceforge.groboutils.junit.v1.MultiThreadedTestRunner;import net.sourceforge.groboutils.junit.v1.TestRunnable;public class ThreadExtendsTest {/** * JUnit单元测试不支持多线程测试,使用GroboUtils进行多线程测试(导入架包)
     * 
     * @throws Throwable     */@Testpublic void test01() throws Throwable {
        MyClass obj = new MyClass();
        obj.count = 10;
        MyThread myth01 = new MyThread(obj);
        MyThread myth02 = new MyThread(obj);
        MyThread myth03 = new MyThread(obj);
        MyTestRunnable t01 = new MyTestRunnable(myth01);
        MyTestRunnable t02 = new MyTestRunnable(myth02);
        MyTestRunnable t03 = new MyTestRunnable(myth03);
        TestRunnable[] tr = new TestRunnable[3];
        tr[0] = t01;
        tr[1] = t02;
        tr[2] = t03;
        MultiThreadedTestRunner mttr = new MultiThreadedTestRunner(tr);
        mttr.runTestRunnables();
    }// 放在主线程中测试public static void main(String[] args) {
        MyClass obj = new MyClass();
        obj.count = 10;
        MyThread t01 = new MyThread(obj);
        MyThread t02 = new MyThread(obj);
        MyThread t03 = new MyThread(obj);
        t01.setName("t01");
        t02.setName("t02");
        t03.setName("t03");
        t01.start();
        t02.start();
        t03.start();
    }
}

 

三 线程生命周期

1.什么是线程的生命周期?

由不同阶段构成的线程从出生到死亡的整个过程,叫做线程的生命周期。

2.线程生命周期的意义

了解线程的生命周期能够更好地掌握线程的运行情况,比如线程的就绪状态,意味着不是调用start方法之后,线程立即执行。

3.生命周期的几个阶段:

  • 出生状态:线程创建完成,尚未开启前的状态。

  • 就绪状态:调用start方法开启线程,线程尚未运行的状态。

  • 运行状态:线程获取CPU时间片执行时的状态。

  • 休眠状态:线程调用sleep方法后进入指定时长的休眠状态,时间结束进入就绪状态。

  • 等待状态:监听对象在线程内部调用wait方法后,线程失去对象锁,进入等待状态。

  • 阻塞状态:线程发出输入或者输出请求后进入阻塞状态。

  • 死亡状态:run方法执行完毕,线程死亡。

四 线程的加入

一个线程A在另一个线程B内部调用join方法,B线程中止,A线程开始执行,A线程执行完毕,B线程才开始执行。

五 线程优先级

线程优先级设定了线程获取CPU时间片的概率,仅仅是一种概率,不能保证优先级高的线程一定优先获得CPU时间片。

线程优先级分为10个等级,从1-10,数值越大,优先级越高,通过setProprity(int)方法设置。

六 线程礼让

Thread.yield,线程礼让只是通知当前线程可以将资源礼让给其他线程,并不能保证当前线程一定让出资源。

七 同步机制

1.什么是线程同步机制?

使得同一资源同一时刻只能有一个线程访问的安全机制,即一个线程访问完毕,其他线程才能访问。

Notion AI
Notion AI

Notion是一款集成了笔记、知识库、数据表格、看板、日历等多种能力于一体的应用程序,它既可供个人使用,也可以与他人进行跨平台协作。

下载

2.同步机制的目的

由于目标资源同一时刻只有一个线程访问,解决了线程安全问题。

3.什么是线程安全问题?

⑴线程安全问题产生条件

  • 多线程并发访问。

  • 存在可修改的共享数据。

⑵第一个线程获取了共享数据,操作结束前,第二个线程修改了该数据,导致第一个线程运算时采用的不是获取时的数据。

4.同步机制解决线程安全问题的原理

synchronized(共享对象){ 修改共享数据的代码 }

上述操作给修改共享数据的代码加了一把对象锁。任何一个对象只有一把对象锁,线程只有获得了对象锁才能访问加锁的资源。一个线程获取了对象锁,执行加锁的代码,执行完毕,归还对象锁,其他线程开始争夺对象锁,访问资源。

5.类锁

synchronized关键字加到静态方法上时,形成类锁,执行该方法上必须获取类锁。

类锁与对象锁是两种不同的锁,允许一个线程持有类锁,另一个线程持有对象锁。

6.synchronized关键字

synchronized关键字加在成员方法,该方法成为同步成员方法,由于一个对象只有一把对象锁,一个线程访问了一个同步成员方法,其他线程不能访问其他同步成员方法。

同步方法不可以被继承,同步方法在子类中失去同步机制。

7.判断条件的设置

在同步机制中,如果同步代码的执行需要满足一定条件,那么将判断条件放在锁内,保证当前获取了锁的线程在执行同步代码时满足执行条件。如果放在锁外,有可能出现当前线程获取了锁以后不满足执行条件的情况。

不存在线程安全问题的做法:

public void run() {
        System.out.println("obj=" + obj);while (true) {synchronized (obj) {if (obj.count > 0) {try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "----当前数量=" + obj.count--);
                } elsereturn;
            }
        }

    }

如果将判断条件obj.count>0放在while语句中,可能出现某个线程进入while语句时count为1,满足条件,进入,等待获取对象锁。当前持有对象锁的线程执行完毕,count变为0,等待线程获取对象锁,在count=0的情况下执行同步块,判断条件失效。

 

八 死锁

1.什么是死锁?

线程A需要多把锁,线程B持有A缺少的锁,缺少A持有的锁,由于线程在获取到全部的锁之前不会释放持有的锁,这使得线程A与线程B陷入僵持,整个进程处于停滞状态。

2.怎么避免死锁?

减少同步机制中锁的数目,尽量避免同一把锁出现在多处。

九 守护线程

1.用户线程?

一般情况下创建的线程都是用户线程,即该线程未被显式设定为守护线程,未在守护线程内部创建。

2.主线程属于用户线程。

3.什么是守护线程?

运行在后台、为用户线程提供服务的线程。

4.守护线程创建

用户线程调用setDaemon(true)方法,或者在守护线程内部创建线程。

5.守护线程的作用

守护线程用于为用户线程提供服务,如垃圾回收器。

6.JVM在所有的用户线程执行完毕后终止,无论此时守护线程是否执行完毕。

7.守护线程运行在后台,所有用户线程结束后,自动结束。

十 wait与sleep方法对比

1.存在范围

  • wait方法是Object级的,即java中的任何一个对象都拥有该方法,像toString一样。

  • sleep方法只在Thread及其子类中存在。

2.作用

  • sleep使当前线程休眠,释放CPU时间片,不会释放持有的锁。

  • wait用于线程间通信,由对象管理所有以该对象为锁的全部线程。在同步代码中由锁对象调用,使当前线程释放持有的对象锁。

3.使用方法

  • sleep方法是一个静态方法,直接通过Thread调用,Thread.sleep。

  • 用在同步代码中,由锁对象调用。

4.相关方法

  • obj.notify():随机唤醒对象监听器上的一个线程,该线程进入就绪状态,一旦获得对象锁与CPU时间片,从等待处接着执行,不是重新进入run方法或者同步代码中。

  • obj.notifyAll():唤醒对象监听器上所有的等待线程,使它们全部进入就绪状态。

十一 ThreadLocal

1.线程局部变量,为每一个线程提供一个变量的副本,使得各个线程相对独立地操作变量,避免线程安全问题。

2.首先必须明确一点,ThreadLocal.get()获取的变量副本必须手动传入:

ThreadLocal.set(Object obj)

初次获取时,判断线程局部变量中是否保存有变量副本,如果没有则手动传入,在该线程中下次获取的就是初次传入的对象。

3.ThreadLocal的目的是保证在一个线程内部,一次创建,多次获取。

4.基本原理:
      将初次传入的变量与线程绑定,线程不变,变量不变。

十二 GroboUtils多线程测试

   1.JUnit测试不支持多线程,GroboUtils提供了对多线程测试的支持,使用时需要导入架包。

    2.几个比较重要的类:

  • TestRunnable:实现了Runnable接口,run方法中运行的是runTest方法,runTest方法是一个抽象方法。

  • MultiThreadedTestRunner:负责管理并开启多个线程。

    3.测试步骤

⑴继承TestRunnable,实现其中的抽象方法runTest,将需要运行的代码放入该方法中。通常为子类定义一个有参构造方法,方法形参为需要测试的线程,在runTest方法中调用测试线程的run方法,从而将将需要执行的代码注入runTest方法中。

⑵创建测试线程数组,将需要测试的TestRunnable实现类传入其中:

TestRunnable[] tr=new TestRunnable[len];

⑶根据测试线程数组创建线程管理与运行对象并开启多线程:

MultiThreadedTestRunner mttr=new MultiThreadedTestRunner(tr);
mttr.runTestRunnables();

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Golang 生态工具与框架:扩展开发能力
Golang 生态工具与框架:扩展开发能力

《Golang 生态工具与框架》系统梳理 Go 语言在实际工程中的主流工具链与框架选型思路,涵盖 Web 框架、RPC 通信、依赖管理、测试工具、代码生成与项目结构设计等内容。通过真实项目场景解析不同工具的适用边界与组合方式,帮助开发者构建高效、可维护的 Go 工程体系,并提升团队协作与交付效率。

1

2026.02.24

Golang 性能优化专题:提升应用效率
Golang 性能优化专题:提升应用效率

《Golang 性能优化专题》聚焦 Go 应用在高并发与大规模服务中的性能问题,从 profiling、内存分配、Goroutine 调度、GC 机制到 I/O 与锁竞争逐层分析。结合真实案例讲解定位瓶颈的方法与优化策略,帮助开发者建立系统化性能调优思维,在保证代码可维护性的同时显著提升服务吞吐与稳定性。

2

2026.02.24

Golang 面试题精选:高频问题与解答
Golang 面试题精选:高频问题与解答

Golang 面试题精选》系统整理企业常见 Go 技术面试问题,覆盖语言基础、并发模型、内存与调度机制、网络编程、工程实践与性能优化等核心知识点。每道题不仅给出答案,还拆解背后的设计原理与考察思路,帮助读者建立完整知识结构,在面试与实际开发中都能更从容应对复杂问题。

1

2026.02.24

Golang 运行与部署实战:从本地到云端
Golang 运行与部署实战:从本地到云端

《Golang 运行与部署实战》围绕 Go 应用从开发完成到稳定上线的完整流程展开,系统讲解编译构建、环境配置、日志与配置管理、容器化部署以及常见运维问题处理。结合真实项目场景,拆解自动化构建与持续部署思路,帮助开发者建立可靠的发布流程,提升服务稳定性与可维护性。

3

2026.02.24

Golang 疑难杂症解决指南:常见问题排查与优化
Golang 疑难杂症解决指南:常见问题排查与优化

《Golang 疑难杂症解决指南》聚焦开发过程中常见却棘手的问题,从并发模型、内存管理、性能瓶颈到工程化实践逐步拆解。通过真实案例与调试思路,帮助开发者定位问题根因,建立系统化排查方法。不只给出答案,更强调分析路径与工具使用,让你在复杂 Go 项目中具备持续解决问题的能力。

1

2026.02.24

Golang 入门学习路线:从零基础到上手开发
Golang 入门学习路线:从零基础到上手开发

Golang 入门路线涵盖从零到上手的核心路径:首先打牢基础语法与切片等底层机制;随后攻克 Go 的灵魂——接口设计与 Goroutine 并发模型;接着通过 Gin 框架与 GORM 深入 Web 开发实战;最后在微服务与云原生工具开发中进阶,旨在培养具备高性能并发处理能力的后端工程师。

0

2026.02.24

中国研究生招生信息网官方网站入口 研招网网页版在线入口
中国研究生招生信息网官方网站入口 研招网网页版在线入口

中国研究生招生信息网入口(https://yz.chsi.com.cn) 此网站是研究生报名入口的唯一官方网站

95

2026.02.24

苹果官网入口与在线访问指南_中国站点快速直达与iPhone查看方法
苹果官网入口与在线访问指南_中国站点快速直达与iPhone查看方法

本专题汇总苹果官网最新可用入口及中国站点访问方式,涵盖官网直达链接、iPhone官方页面查看方法与常见访问说明,帮助用户快速进入苹果官方网站,便捷了解产品信息与官方服务。

14

2026.02.24

Asianfanfics官网入口与访问指南_AFF官方平台最新登录地址
Asianfanfics官网入口与访问指南_AFF官方平台最新登录地址

本专题系统整理Asianfanfics(AFF)官方网站最新可用入口,涵盖官方平台最新直达地址、官网登录方式及中文访问指引,帮助用户快速、安全地进入AFF平台浏览与使用相关内容。

15

2026.02.24

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.4万人学习

Node.js 教程
Node.js 教程

共57课时 | 12万人学习

CSS3 教程
CSS3 教程

共18课时 | 6.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号