版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第8章多线程《Java基础案例教程》(第3版)学习目标/Target了解线程的创建和启动,能够简述3种创建和启动线程的方式熟悉线程的生命周期及状态转换,能够简述线程生命周期中的六种基本状态和它们之间相互转换的方式熟悉线程安全问题,能够简述多线程程序出现线程安全问题的原因了解线程和进程,能够简述进程与线程的概念了解线程同步,能够简述实现线程同步的3种方式学习目标/Target掌握线程同步的方式,能够使用同步代码块、同步方法、Lock锁这3种方式同步线程了解线程池,能够简述线程池的概念以及优点熟悉线程池的使用,能够使用ThreadPoolExecutor创建线程池对象,并使用线程池对象执行线程任务熟悉线程的控制,能够通过线程优先级、线程休眠、线程让步和线程插队实现对线程的控制掌握线程的创建和启动,能够使用继承Thread类、实现Runnable接口、基于Callable接口和FutureTask类这3种方式创建线程章节概述/
Summary日常生活中,许多事情都是并行执行的。例如,人可以同时进行呼吸、血液循环、思考问题等活动。在一个应用程序中也可以同时存在多个执行路径,每个执行路径独立执行不同的任务或代码块,这种有多条并发执行路径的程序,称为多线程程序。本章将对多线程的相关知识进行详细讲解。目录/Contents0102线程与进程线程的创建和启动03线程的生命周期及状态转换目录/Contents0405线程同步线程的控制06线程池线程与进程8.18.1线程与进程了解线程和进程,能够简述进程与线程的概念
先定一个小目标!8.1线程与进程一台计算机可以同时运行多个程序,每个运行中的程序都是一个进程,每个进程拥有自己的资源和状态,具有一个相对独立的执行环境。进程是程序的实例,是操作系统动态执行的基本单元。虽然计算机允许多个程序同时运行,但实际上计算机中单核的CPU同一时刻只能处理一个进程,用户之所以认为同时会有多个进程在运行,是因为计算机系统采用了“多道程序设计”技术。8.1线程与进程多道程序设计,是指计算机允许多个相互独立的程序同时进入内存,并相互穿插运行。多道程序技术将CPU的整个生命周期划分为相同的时间片,每个CPU时间片内只处理一个进程,但由于CPU划分的时间片很微小,且运行速度快,所以宏观上表现为计算机可以同时运行多个程序,处理多个进程。8.1线程与进程进程的实质是程序在多道程序系统的一次执行过程,但进程的实际运作单位是线程。线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中。每个进程中至少存在一个线程,每一个线程都是进程中一个单一顺序的控制流。8.1线程与进程一个进程中的多个线程可以并行执行不同的任务。在前面章节的程序中,代码都是按照调用顺序依次执行,没有出现两段程序代码交替运行的效果,这样的程序称作单线程程序。如果希望程序中实现多段程序代码交替运行的效果,则需要在程序中创建多个线程,即多线程程序。一个多线程程序在执行过程中会产生多个线程,这些线程可以并发执行并相互独立,其执行过程的示意图如下图所示。线程的创建和启动8.28.2线程的创建和启动掌握线程的创建和启动,能够使用继承Thread类、实现Runnable接口、基于Callable接口和FutureTask类这3种方式创建线程
先定一个小目标!8.2线程的创建和启动要编写多线程程序,需要在程序中创建并启动除主线程之外的其他线程。Java中使用Thread类来代表线程,所有的线程对象都必须是Thread类或其子类的实例。Thread类提供给了用于分配线程对象的构造方法,常用构造方法如下。方法声明说明Thread()创建一个线程对象Thread(Stringname)创建一个名称为name的线程对象Thread(Runnabletarget)根据任务对象target创建一个线程对象Thread(Runnabletarget,Stringname)根据任务对象target创建一个线程对象,并指定线程对象的名称为name如果未指定线程名字,程序会自动为线程分配格式为“Thread-n”的名称,n为非负整数的数字。8.2线程的创建和启动Thread类提供多种方法用于操作线程,其中常用方法如下表所示。方法声明说明StringgetName()获取当前线程的名称voidsetName(Stringname)将当前线程的名称更改为参数namevoidstart()启动一个新线程voidrun()线程的执行方法,是线程执行的主体staticvoidsleep(longmillis)使当前正在执行的线程休眠millis毫秒staticThreadcurrentThread()返回对当前正在执行的线程对象的引用8.2线程的创建和启动Thread类用于操作线程的方法,在使用时的注意事项。start()方法用于启动一个新线程,但是该方法本身并不是执行线程代码的方法。start()方法只是告诉JVM该线程已准备好被执行,并由JVM来负责调度和执行。当线程获得了CPU时间片后,就会调用该线程的run()方法,run()方法是线程的执行方法,其中包含线程的主要执行逻辑。如果直接调用run()方法,则该方法并不会启动线程,只是在当前线程中执行了run()方法中的代码而已。8.2线程的创建和启动Java提供了多种创建线程的方式,其中常用的创建方式有继承Thread类、实现Runnable接口、基于Callable接口和FutureTask类实现,下面分别对这三种创建方式进行讲解。8.2线程的创建和启动1.继承Thread类创建线程通过继承Thread类创建线程的步骤如下。(1)定义Thread类的子类,并重写Thread类的run()方法,在run()方法中定义线程要执行的任务。(2)创建Thread子类的实例,即创建线程对象。(3)调用线程对象的start()方法启动线程。8.2线程的创建和启动1.继承Thread类创建线程下面通过一个案例演示如何通过继承Thread类的方法创建和启动线程。(1)定义线程类定义MyThread01类继承Thread类,并重写Thread类的run()方法,在run()方法中循环输出当前执行线程的线程对象名称。MyThread01.java源代码8.2线程的创建和启动1.继承Thread类创建线程(2)启动线程定义测试类Example01
,在类中的main()方法内创建两个MyThread01线程对象,并启动线程。Example01.java源代码8.2线程的创建和启动1.继承Thread类创建线程(3)测试效果运行文件Example01.java,运行效果如下图所示。8.2线程的创建和启动2.实现Runnable接口创建线程由于Java只支持单继承,所以如果一个类继承了某个父类之后,就无法再通过继承Thread类创建线程。为了解决这个问题,可以借助Thread类提供的Thread(Runnabletarget)或Thread(Runnabletarget,Stringname)构造方法来创建线程。其中Runnable接口的实例代表一个需要执行的具体任务,通常被称为任务对象。Runnable接口只包含一个run()方法,用于定义线程的执行代码。8.2线程的创建和启动2.实现Runnable接口创建线程通过实现Runnable接口创建多线程的步骤如下。(1)定义Runnable接口的实现类,并重写该接口的run()方法。(2)创建Runnable实现类的实例,并将实例作为Thread的任务对象创建Thread对象。(3)调用线程对象的start()方法启动线程。8.2线程的创建和启动2.实现Runnable接口创建线程下面通过一个案例演示如何通过实现Runnable接口创建和启动线程。(1)定义Runnable接口的实现类定义类MyRunnable01实现Runnable接口,并重写接口中的run()方法。MyRunnable01.java源代码8.2线程的创建和启动2.实现Runnable接口创建线程(2)启动线程定义测试类Example02
,在类中的main()方法内创建1个MyRunnable01线程任务对象和2个Thread线程对象,并启动线程。Example02.java源代码8.2线程的创建和启动2.实现Runnable接口创建线程(3)测试效果运行文件Example02.java文件,效果如下图所示。8.2线程的创建和启动3.基于Callable接口和FutureTask类创建线程通过实现Runnable接口创建线程时,将重写的run()方法包装成线程执行体。由于run()方法没有返回值,因此如果线程执行结果需要返回时,实现Runnable接口的方式就太不合适了。为此,Java提供了Callable接口,该接口的call()方法可以作为线程的执行体,并且有返回值。8.2线程的创建和启动3.基于Callable接口和FutureTask类创建线程Callable对象不能直接作为Thread构造方法的target参数,需要借助FutureTask类创建对应的参数对象,FutureTask类提供的构造方法可以传入一个Callable对象将其封装起来,在创建Thread对象时,可以将FutureTask对象作为Thread的target参数传入。当线程执行时,FutureTask内部会执行Callable对象的call()方法,并将结果存储在FutureTask中。8.2线程的创建和启动3.基于Callable接口和FutureTask类创建线程FutureTask类的继承关系如下图所示。8.2线程的创建和启动3.基于Callable接口和FutureTask类创建线程FutureTask是Runnable接口和Future接口的间接实现类。其中,Future接口用于管理线程返回结果,它共有5个方法,具体如下表所示。方法声明功能描述booleancancel(booleanmayInterruptIfRunning)用于尝试取消任务,参数mayInterruptIfRunning表示是否允许取消正在执行却没有执行完毕的任务,如果设置true,则表示可以取消正在执行的任务booleanisCancelled()判断任务是否被取消,如果被取消返回true,否则返回falsebooleanisDone()判断任务是否已经完成,如果任务完成返回true,否则返回falseVget()用于获取执行结果,这个方法会发生阻塞,一直等到任务执行完毕才返回执行结果Vget(longtimeout,TimeUnitunit)用于在指定时间内获取执行结果,如果在指定时间内无法获取到结果则抛出异常8.2线程的创建和启动3.基于Callable接口和FutureTask类创建线程基于Callable和FutureTask创建线程的步骤如下。(1)创建Callable接口的实现类。(2)创建包装了Callable对象的FutureTask类。(3)使用FutureTask对象作为Thread对象的target参数并启动线程。8.2线程的创建和启动3.基于Callable接口和FutureTask类创建线程下面通过一个案例演示如何基于Callable和FutureTask创建和启动线程。(1)定义Callable接口实现类定义MyCallable01类实现Callable接口,并重写Callable接口的call()方法。Callable接口是泛型接口,可以在泛型中定义call()方法的返回值类型。MyCallable01.java源代码8.2线程的创建和启动3.基于Callable接口和FutureTask类创建线程(2)启动线程定义测试类Example03,在类中的main()方法内创建Callable线程任务对象,并通过FutureTask对象将线程任务对象进行封装,将FutureTask对象作为Thread线程对象的target参数进行创建线程对象,并启动线程。Example03.java源代码8.2线程的创建和启动3.基于Callable接口和FutureTask类创建线程(3)测试效果运行文件Example03.java,效果如下图所示。8.2线程的创建和启动继承Thread类、实现Runnable接口、基于Callable和FutureTask三种创建线程方式的优缺点。创建方式优点缺点继承Thread类编码相对简单存在单继承的局限性,不便于扩展不能返回线程执行的结果每个线程的任务和线程本身是耦合的,无法将任务和线程分离实现Runnable接口可以继续继承类和实现接口,扩展性强任务和线程分离,可以实现多个线程共享同一个任务编程相对复杂,不能返回线程执行的结果基于Callable和FutureTask线程任务类只是实现接口,可以继续继承类和实现接口,扩展性强。可以在线程执行完毕后去获取线程执行的结果。编码相对复杂线程的生命周期及状态转换8.38.3线程的生命周期及状态转换熟悉线程的生命周期及状态转换,能够简述线程生命周期中的六种基本状态和它们之间相互转换的方式
先定一个小目标!8.3线程的生命周期及状态转换无限等待状态被终止状态计时等待状态新建状态阻塞状态可运行状态8.3线程的生命周期及状态转换(1)新建状态创建一个线程对象,但还没调用start()方法启动线程,该线程就处于新建状态。此时,新建状态的线程和其他声明但未赋值的Java对象类似,JVM仅为其分配了内存,并没有表现出任何线程的动态特征。8.3线程的生命周期及状态转换(2)可运行状态当线程对象调用了start()方法后就进入可运行状态,也称为就绪状态。处于可运行状态的线程位于线程队列中,此时它只是具备了运行的条件,要获得CPU的使用权并开始运行,还需要等待系统的调度。8.3线程的生命周期及状态转换(3)阻塞状态如果处于可运行状态的线程获得了CPU的使用权,并开始执行run()方法中的线程执行体,则线程处于运行状态。一个线程启动后,它可能不会一直处于运行状态,当一个线程试图获取一个对象锁,而该对象锁被其他的线程持有时,则该线程进入阻塞状态。当其他线程释放对象锁,该线程获得对象锁时,该线程将重新变成可运行状态。8.3线程的生命周期及状态转换(4)无限等待状态一个线程在等待另一个线程执行一个唤醒动作时,该线程进入无限等待状态。线程进入这个状态后是不能自动唤醒的,必须等待另一个线程调用notify()方法或者notifyAll()方法才能够唤醒。8.3线程的生命周期及状态转换(5)计时等待状态计时等待状态是指线程在调用了具有指定等待时间的方法后而进入的状态,这些方法包括Thread类的sleep()方法和join()方法、Object类的wait()方法、LockSupport类的parkNanos()方法、LockSupport.parkUntil()等。当线程调用这些方法并指定了等待时间,它就会进入计时等待状态,这一状态将一直保持到超时或者接收到唤醒通知。8.3线程的生命周期及状态转换(6)被终止状态被终止状态是终止运行的线程的状态。线程因为run()方法正常退出,或者线程抛出一个未捕获的异常(Exception)或者错误(Error)时终止了run()方法而结束执行。8.3线程的生命周期及状态转换在多线程程序中,线程启动后不能永远独占CPU资源,CPU会在多个线程之间切换执行。因此,线程的状态会在可运行和阻塞之间切换。此外,通过一些操作也可以使线程在不同状态之间转换。线程状态的转换关系如下图所示。线程同步8.48.4线程同步线程同步是指在多线程程序中,当一个线程在对内存中的共享数据进行操作时,其他线程无法对该共享数据进行操作,直到该线程完成操作的机制。这一机制可以确保多个线程按照特定顺序正确执行,从而保证在多线程环境下共享资源的安全访问和正确性。当程序中的线程不同步时,可能会导致线程出现安全问题。8.4.1线程安全问题熟悉线程安全问题,能够简述多线程程序会出现线程安全问题的原因
先定一个小目标!8.4.1线程安全问题采用多线程技术的应用程序可以充分利用CPU的空闲时间片,用尽可能少的时间对用户的请求作出响应,从而提高程序整体运行效率。然而,由于线程调度具有一定的随机性,当多个线程同时访问和操作同一共享资源时,很容易出现偶然的线程安全问题。8.4.1线程安全问题案例演示线程安全问题是指多线程环境中,多个线程同时访问共享数据,如果没有适当的同步保护机制保护共享数据,导致程序可能出现不正确或不符合预期的结果。下面通过一个模拟银行取钱的案例,演示多个线程同时访问和操作同一共享资源产生的安全问题。银行取钱基本流程如下:(1)用户输入取款金额。(2)银行判断账户余额是否大于取款金额。(3)如果余额大于取款金额,则取款成功,否则,取款失败。8.4.1线程安全问题案例演示(1)定义一个账户类Account用于封装账户信息,该类中定义账户编号和余额两个成员变量,以及取钱的方法。Account.java源代码8.4.1线程安全问题案例演示(2)定义取钱的线程类DrawThread,在该线程类的线程执行体中执行取钱操作,每次取100000元。DrawThread.java源代码8.4.1线程安全问题案例演示(3)创建测试类ThreadDemo,在测试类的main()方法中创建账户对象,并启动两个线程从该账户中取钱。ThreadDemo.java源代码8.4.1线程安全问题案例演示(4)运行文件ThreadDemo.java,结果如下图所示。8.4.2线程同步方式掌握线程同步的方式,能够使用同步代码块、同步方法、Lock锁这3种方式实现线程同步
先定一个小目标!8.4.2线程同步方式在多线程程序中,多个线程并发修改共享资源时,可能会导致出现线程安全问题。为避免出现此类问题,可以采用线程同步机制,线程同步的核心思想是保证在任何时刻,只有一个线程可以访问共享资源。常见的线程同步方式有同步代码块、同步方法、Lock接口.8.4.2线程同步方式1.同步代码块同步代码块是一段被synchronized关键字修饰的代码块,可以将处理共享资源的代码放在同步代码块中,以保证在同一时间只有一个线程可以执行该代码块中的内容,实现线程同步。使用synchronized关键字创建同步代码块的语法格式如下:synchronized(obj){ …此处编写操作共享资源的代码}obj是一个对象,作为锁使用,只有持有该锁的线程才可以执行同步代码块中的代码。obj可以为任意一个对象,也可以是类的字面常量。8.4.2线程同步方式1.同步代码块下面使用同步代码块解决模拟银行取钱案例中的安全问题,修改Account.java文件中的drawMoney()方法,将取钱修改余额的代码放入同步代码块中。使用同步代码块修改drawMoney()方法源代码8.4.2线程同步方式1.同步代码块修改完成后,运行ThreadDemo.java文件,效果如下图所示。8.4.2线程同步方式2.同步方法synchronized关键字还可以用于修饰方法,称为同步方法。和同步代码块类似,同步方法在同一时刻只允许一个线程执行。对于实例同步方法,默认使用当前实例对象作为锁对象,而对于静态同步方法,则默认使用类对象作为锁对象,即使用类名.class对象作为锁对象。同步方法的synchronized关键字需要放在方法的返回值类型之前,具体语法格式如下:[修饰符]synchronized返回值类型方法名([参数1,...]){}8.4.2线程同步方式2.同步方法下面使用同步方法解决模拟银行取钱案例的线程安全问题,将Account.java文件中的drawMoney()方法修改为同步方法。使用同步方法修改drawMoney()方法源代码8.4.2线程同步方式2.同步方法8.4.2线程同步方式3.Lock接口同步代码块和同步方法使用的是封闭式的锁机制,使用起来比较简单,也能够解决线程安全问题,但也存在一些限制,例如对于等待获取锁的线程,无法中断其等待。即使等待时间很长,无法得到锁,也只能一直等待下去,无法中途终止。这可能会导致系统资源的浪费。8.4.2线程同步方式3.Lock接口为了更清晰地表达如何加锁和释放锁,从Java5开始,Java提供了一种功能强大的线程同步方式,即使用Lock接口相应的实现类充当同步锁来实现同步。Lock对象可以让某个线程在持续获取同步锁失败后返回,而不再继续等待,提供了比同步代码块和同步方法更广泛的锁操作。8.4.2线程同步方式3.Lock接口Lock是接口不能直接实例化,常用的是Lock接口的实现类ReentrantLock(可重入锁)
。使用Lock对象可以显式地加锁、释放锁,加锁的方法为lock(),释放锁的方法为unlock()。使用ReentrantLock的代码格式如右所示。class类名{//定义锁对象privateReentrantLockreentrantLock=newReentrantLock();//需要保障线程安全的方法publicvoid方法名(){reentrantLock.lock();//加锁
try{//需要保证线程安全的代码……}finally{reentrantLock.unlock();
//释放锁
}}}8.4.2线程同步方式3.Lock接口下面使用ReentrantLock解决模拟银行取钱案例的线程安全问题,修改Account.java文件中的drawMoney()方法,使用ReentrantLock进行加锁。使用ReentrantLock修改drawMoney()方法源代码8.4.2线程同步方式3.Lock接口修改完成后,运行ThreadDemo.java文件,效果如下图所示。线程的控制8.58.5线程的控制熟悉线程的控制,能够使用线程优先级、线程休眠、线程让步和线程插队实现线程的控制
先定一个小目标!8.5线程的控制多线程程序中的各个线程是并发执行的,但不是同一时刻执行。要执行某个线程,它必须获得CPU的使用权。Java虚拟机根据特定的机制为程序中的每个线程分配CPU的使用权。如果需要在程序中控制线程的执行,可以使用线程优先级、线程休眠、线程让步和线程插队四种方式来实现。8.5线程的控制1.线程的优先级程序运行期间,每个线程都有自己的优先级,较高优先级的线程具有更大概率获得CPU的使用权。为方便操作线程的优先级,Thread类提供了setPriority(intnewPriority)方法来设置线程的优先级,同时还提供了getPriority()方法用于获取线程的优先级。8.5线程的控制1.线程的优先级线程的优先级使用1~10之间的整数表示,数字越大表示优先级越高。线程的优先级可以直接使用对应的整数进行设置,也可以使用Thread类中的三个静态常量进行设置,具体如下表所示。静态常量功能描述intMAX_PRIORITY表示线程的最高优先级,相当于值10intMIN_PRIORITY表示线程的最低优先级,相当于值1intNORM_PRIORIY表示线程的普通优先级,相当于值58.5线程的控制1.线程的优先级下面通过一个案例演示程序中不同优先级线程的运行情况。Example04.java源代码8.5线程的控制1.线程的优先级案例的运行结果如下图所示。8.5线程的控制1.线程的优先级需要说明的是,Java的线程优先级依赖于底层操作系统的支持。不同操作系统对线程优先级的支持不同,不保证一致性和可移植性。因此,线程优先级仅用于提高程序执行效率,而不适用于实现特定功能。8.5线程的控制2.线程休眠如果想要控制线程执行顺序,使正在执行的线程暂停,将CPU使用权让给其他线程,可以使用Thread类的sleep()静态方法,该方法会使当前线程进入睡眠状态,让出CPU使用权,从而让其他线程有机会执行。Thread的sleep()方法接收一个表示线程要暂停的时间参数,单位为毫秒。线程在暂停期间不会执行任何操作。暂停时间过后,线程会重新进入就绪状态,等待CPU的调度再次执行。sleep()方法可能会抛出InterruptedException异常,因此,需要在调用该方法的地方处理或声明抛出InterruptedException异常,以便对程序可能出现的中断进行适当的响应。8.5线程的控制3.线程让步线程让步是让当前线程放弃对CPU的占用,使其他具有相同或更高优先级的线程有机会继续执行的一种操作,可以通过Thread类的yield()方法实现。yield()方法和sleep()方法有些类似,都可以让当前正在运行的线程暂停,区别在于yield()方法不会阻塞该线程,只是将其转换成就绪状态。8.5线程的控制3.线程让步下面通过一个案例演示yield()方法的使用。Example05.java源代码8.5线程的控制3.线程让步案例的运行结果如下图所示。8.5线程的控制4.线程插队在Java中,线程插队是一种线程控制方式,它允许一个线程等待另一个线程执行结束后,然后再继续执行。通过Thread类中的join()方法可以实现线程插队的效果,当一个线程对象在当前线程中调用join()方法后,当前线程会等待调用join()方法的线程对象所在线程完成执行后再继续执行自己的任务。8.5线程的控制4.线程插队下面通过一个案例演示使用join()方法实现的线程插队效果。Example06.java源代码8.5线程的控制4.线程插队案例的运行结果如下图所示。线程池8.68.6线程池熟悉线程池的使用,能够使用ThreadPoolExecutor创建线程池对象,并通过线程池对象执行线程任务
先定一个小目标!8.6线程池线程池是一个可以复用线程的技术,它是一个容纳多个线程的容器。在程序启动时,线程池会预先创建指定数量的线程,并让它们处于空闲状态。当程序传递一个任务给线程池时,线程池会选择一个空闲线程来执行任务。任务执行完毕后,线程会返回线程池并重新转换为空闲状态,等待下一个任务的执行。8.6线程池在Java中,Executor接口是线程池的顶级接口,它定义了执行指定任务的方法,但没有规定线程池的具体实现方式。创建线程池对象通常通过Executor的子类ExecutorService的实现类ThreadPoolExecutor创建,ThreadPoolExecutor提供了4个构造方法创建线程池对象,它们的区别只是参数的数量和类型不同,其中参数最全的构造方法的语法格式如下。publicThreadPoolExecutor(intcorePoolSize,intmaximumPoolSize,
longkeepAliveTime,
TimeUnitunit, BlockingQueue<Runnable>workQueue,
ThreadFactorythreadFactory,
RejectedExecutionHandlerhandler)8.6线程池ThreadPoolExecutor类的构造方法的参数所代表的含义如下。corePoolSize:线程池的核心线程数量,不能小于0。maximumPoolSize:线程池支持的最大线程数,最小数量应大于等于核心线程数量。keepAliveTime:临时线程的最大存活时间,不能小于0。unit:存活时间的单位,可以是秒、分、时、天。workQueue:任务队列,不能为null。threadFactory:创建线程的线程工厂。handler:线程池无法处理新任务时的拒绝策略。当线程池已达到最大线程数并且任务队列已满时,新提交的任务就会被拒绝执行。8.6线程池Java根据不同场景的需求提供了几种RejectedExecutionHandler处理策略,具体如下表所示。策略说明ThreadPoolExecutor.AbortPolicy丢弃任务并抛出RejectedExecutionException异常,ThreadPoolExecutor的默认策略ThreadPoolExecutor.DiscardPolicy丢弃任务,但是不抛出异常,不推荐使用ThreadPoolEx
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- Linux系统管理及应用项目式教程课件 项目6 管理软件包与进程
- 班主任工作范文小学班主任工作计划三
- 高二上学期数学人教A版(2019)期末模拟测试卷A卷(含解析)
- 网络安全基础技术应用知到智慧树章节测试课后答案2024年秋深圳信息职业技术学院
- 《福利国家》课件
- 2025届福建闽侯第六中学高三最后一卷数学试卷含解析
- 广东普宁华侨中学2025届高考语文一模试卷含解析
- 两个矩阵的等价、相似、合同的关系
- 河南省舞钢市第二高级2025届高三第二次模拟考试英语试卷含解析
- 放弃治疗协议书 篇三
- 金融理论与政策(华南农业大学)-中国大学MOOC答案2023版
- 精读《未来简史》学习通超星期末考试答案章节答案2024年
- 2024年《论教育》全文课件
- 2024年湖南长沙市公安局监所管理支队招聘13人历年高频难、易错点500题模拟试题附带答案详解
- 灌装车间员工岗位职责
- 国家开放大学专科《法理学》(第三版教材)形成性考核试题及答案
- 劳动教育概论智慧树知到期末考试答案章节答案2024年哈尔滨工业大学
- (正式版)SHT 3158-2024 石油化工管壳式余热锅炉
- 如何做好制程品质控制培训讲学
- 第三章无人机结构PPT课件
- 学校安全管理网络图
评论
0/150
提交评论