




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、1,自学软件开发(PPT版),本章主要讲述如下内容: 多线程的概念; 线程的生命周期; 多线程编程中的常量和方法; 线程调度方法; 资源冲突与协调; 线程之间的通信。,2,9.1 简介,9.1.1 什么是线程 一般来说,我们把正在计算机中执行的程序叫做“进程”(Process) ,而不将其称为程序(Program)。所谓“线程”(Thread),是“进程”中某个单一顺序的控制流。 线程在程序中是独立的、并发的执行路径 线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。,3,
2、进程就是在某种程度上相互隔离的、独立运行的程序。 线程是进程内部的单一控制序列流。一个进程可以具有多个并发的线程。 进程可以支持多个线程,它们看似同时执行,但互相之间并不同步。(CPU只是将时间切割为时间片,然后将时间片分配给这些线程,CPU的高速计算能力,给人的感觉就像是多个线程在同时执行一样。) 进程中的所有线程共享进程的虚拟地址空间,这意味着所有线程都可以访问进程的全局变量和资源。这一方面为编程带来了方便,但另一方面也容易造成冲突。,线程和进程,4,9.3 JAVA线程,9.3.1 实现方式 Java程序通过流控制来执行程序流,程序中单个顺序的流控制称为线程,多线程则指的是在单个程序中可
3、以同时运行多个不同的线程,执行不同的任务 Java里面实现多线程,有2个方法 继承Thread类(位于java.lang包内) 实现Runnable接口 一般鼓励使用第二种方法,因为Java里面只允许单一继承,但允许实现多个接口。第二个方法更加灵活,5,每个线程都是通过某个特定Thread对象所对应的方法run( )来完成其操作的 方法run( )称为线程体 使用start() 方法启动线程 启动线程是使线程进入到可运行(runnable)状态,并不一定立即开始执行该线程,9.3 JAVA线程,6,public class HelloThread extends Thread public v
4、oid run() System.out.println(I extend Thread.); ,Java实现线程,方法一:继承Thread,继承Thread,线程体,所有的操作都发生在线程体中,public class TestHello public static void main(String args) HelloThread helloThread = new HelloThread(); helloThread.start(); ,start()方法启动线程,运行结果:I extend Thread.,Java实现线程,方法二:实现Runnable接口,public class
5、HelloRunner implements Runnable public void run() System.out.println(I implements “Runable.); ,实现Runnable,线程体,所有的操作都发生在线程体中,public class TestHello public static void main(String args) HelloRunner runner = new HelloRunner(); Thread thread = new Thread(runner); thread.start(); ,start()方法启动线程,运行结果:I im
6、plement Runnable.,启动线程是使线程进入到可运行(runnable)状态,并不一定立即开始执行该线程,实例化线程,实例化线程,7,两种创建线程方法的比较,使用Runnable接口 形成清晰的模型; 还可以从其他类继承; 保持程序风格的一致性。 直接继承Thread类 不能再从其他类继承; 编写简单,可以直接操纵线程,8,线程属性,线程体 所有的操作都发生在线程体中,在Java中线程体是从Thread类继承的run()方法,或实现Runnable接口的类中的run()方法。当线程产生并初始化后,实时系统调用它的run()方法。run()方法内的代码实现所产生线程的行为,它是线程的
7、主要部分。 线程状态 新线程态 可运行态 运行中状态 等待、阻塞、睡眠状态 死亡态 线程优先级,9,9.3.4 线程状态,新建状态、初始化状态: 线程对象已经被创建,但是还没有被启动时的状态。这段时间就是在我们调用new命令之后,调用start()方法之前。 可运行状态、就绪状态: 在我们调用了线程的start()方法之后线程所处的状态。处于RUNNABLE状态的线程在JAVA虚拟机(JVM)上是运行着的,但是它可能还正在等待操作系统分配给它相应的运行资源以得以运行。 运行状态 当线程调度器选择一个线程作为当前执行进程时,该线程就处于运行状态,10,9.3.4 线程状态,等待、阻塞、睡眠状态
8、当以下事件发生时,线程进入非运行态。 suspend()方法被调用; sleep()方法被调用; 线程使用wait()来等待条件变量; 线程处于I/O等待 DEAD(死亡状态): 当run()方法返回,或别的线程调用stop()方法,线程进入死亡态,11,线程的执行特性,一个线程必须处于如下五种可能的状态之一: 初始态/新状态 Runnable 运行中状态: 阻塞/ NonRunnable 死状态,12,13,9.3.5 线程控制基本方法,14,线程状态转换,15,9.3.6 线程状态转换,public class TestThreadStatus extends Thread / 构造函数
9、public TestThreadStatus(String name) super(name); public void run() try System.out.print(Thread.currentThread().getName(); System.out.println(将进入暂停状态。现在时间: + new Date(); Thread.sleep(2000); System.out.print(Thread.currentThread().getName() + 的状态:); System.out.print(Thread.currentThread().getState();
10、 System.out.println( 现在时间: + new Date(); catch (InterruptedException e) e.printStackTrace(); ,sleep():非运行状态,获得运行状态,/main方法启动线程 public static void main(String args) Thread t1 = new TestThreadStatus(线程); t1.start(); ,运行结果: 线程将进入暂停状态。现在时间:Wed Dec 02 08:40:16 CST 2009 线程的状态:RUNNABLE 现在时间:Wed Dec 02 08:4
11、0:18 CST 2009,16,public class CounterThread extends Thread private int result; public CounterThread(String name) super(name); public int getResult() return result; public void run() try Thread.sleep(3000); System.out.println(Thread.currentThread().getName() + 被阻塞了3000ms); catch (InterruptedException
12、 ex) System.out.println(ex.getMessage(); result = 5; ,9.3.7 加入线程(join方法),17,public class TestThreadJoin public static void main(String args) System.out.println(现在的线程是: + Thread.currentThread().getName(); long start = System.currentTimeMillis(); System.out.println(开始时间: + start); CounterThread ct1 =
13、new CounterThread(线程1); CounterThread ct2 = new CounterThread(线程2); ct1.start(); ct2.start(); long end = System.currentTimeMillis(); System.out.println(结束时间: + start); System.out.println(join花费时间: + (end - start) + ms); int result = ct1.getResult() + ct2.getResult(); System.out.println(计算结果: + resul
14、t); ,线程1启动,线程2启动,运行结果: 现在的线程是:main 开始时间:1259717049841 结束时间:1259717049841 join花费时间:0ms 计算结果:0 线程1被阻塞了3000ms 线程2被阻塞了3000ms,加入jion()方法,public class TestThreadJoin public static void main(String args) System.out.println(现在的线程是: + Thread.currentThread().getName(); long start = System.currentTimeMillis();
15、 System.out.println(开始时间: + start); CounterThread ct1 = new CounterThread(线程1); CounterThread ct2 = new CounterThread(线程2); ct1.start(); try ct1.join(); catch (InterruptedException e) System.out.println(e.getMessage(); ct2.start(); try ct2.join(); catch (InterruptedException e) System.out.println(e.
16、getMessage(); long end = System.currentTimeMillis(); System.out.println(结束时间: + start); System.out.println(join花费时间: + (end - start) + ms); int result = ct1.getResult() + ct2.getResult(); System.out.println(计算结果: + result); ,Thread.join()让当前线程block住, 等thread执行完之后,再继续执行 。 必须等2个线程都执行完才能汇总, 那么这时候在主线程里面
17、让2个线程join, 最后计算结果既可,运行结果: 现在的线程是:main 开始时间:1259717860458 线程1被阻塞了3000ms 线程2被阻塞了3000ms 结束时间:1259717860458 join花费时间:6022ms 计算结果:10,18,9.3.8 线程优先级与调度,线程的优先级用数字来表示,范围从1到10,一个线程的缺省优先级是5 Thread.MIN_PRIORITY = 1 Thread.MAX_PRIORITY = 10 Thread.NORM_PRIORITY = 5 int getPriority()方法获得线程对象的优先级 setPriority(int
18、newPriority)方法设置优先级 Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程。线程调度器按照线程的优先级决定应调度哪些线程来执行 多数线程的调度是抢先式的。即如果在当前线程执行过程中,一个更高优先级的线程进入可运行状态,则这个线程立即被调度执行.,19,9.3.9 共享受限资源,多线程的出现,可以同时做多件事情。但是当一个资源是受限制的资源的时候,多个线程进行访问就会出现一些问题。必须防止这类资源访问冲突的问题,否则就会出现多个线程访问同一个银行账户,多个买家同时拍下一个宝贝之类的问题。,如何避免呢,20,使用资源的时候给它上把 “锁” JAVA通过synchro
19、nized实现锁,21,同步线程synchronized,Java中的多线程使用 synchronized关键字实现同步。为了避免线程中使用共享资源的冲突,当线程进入 synchronized的共享对象时,将为共享对象加上锁,阻止其他的线程进入该共享对象。的问题: synchronized关键字可以作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块。如果再细的分类,synchronized可作用于instance变量、object reference(对象引用)、static函数和class literals(类名称字面常量)身上。 无论synchronized关键字加
20、在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或函数当作锁而且同步方法很可能还会被其他线程的对象访问。 每个对象只有一个锁(lock)与之相关联。 实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。,22,订票系统,public class TicketsThread implements Runnable int tickets = 3; public void run() while (tickets 0) sale(); public void sale() if (tickets 0) try Thread.sleep(1); catch (
21、Exception e) System.out.println(e.getMessage(); tickets-; / 卖掉一张票 System.out.println(Thread.currentThread().getName() + 卖掉一张票,现在剩余: + tickets); ,剩余票数,线程体,售票业务,售票窗口,public class TicketOffice public static void main(String args) TicketsThread t = new TicketsThread(); new Thread(t).start(); new Thread(
22、t).start(); ,运行结果: Thread-0卖掉一张票,现在剩余:2 Thread-1卖掉一张票,现在剩余:1 Thread-1卖掉一张票,现在剩余:0 Thread-0卖掉一张票,现在剩余:-1,23,订票系统,public class TicketsThread implements Runnable int tickets = 3; public void run() while (tickets 0) sale(); public synchronized void sale() if (tickets 0) try Thread.sleep(1); catch (Excep
23、tion e) System.out.println(e.getMessage(); tickets-; / 卖掉一张票 System.out.println(Thread.currentThread().getName() + 卖掉一张票,现在剩余: + tickets); ,加入synchronized修饰符,售票窗口,public class TicketOffice public static void main(String args) TicketsThread t = new TicketsThread(); new Thread(t).start(); new Thread(t
24、).start(); ,运行结果: Thread-0卖掉一张票,现在剩余:2 Thread-1卖掉一张票,现在剩余:1 Thread-1卖掉一张票,现在剩余:0,24,运行结果: Thread-0卖掉一张票,现在剩余:2 Thread-1卖掉一张票,现在剩余:1 Thread-1卖掉一张票,现在剩余:0 Thread-0卖掉一张票,现在剩余:-1,没有synchronized修饰,比较两次运行结果,运行结果: Thread-0卖掉一张票,现在剩余:2 Thread-1卖掉一张票,现在剩余:1 Thread-1卖掉一张票,现在剩余:0,有synchronized修饰,25,9.3.10 死锁,因
25、为线程可以阻塞,并且对象可以具有同步控制方法,用以防止别的线程在锁还没有释放的时候就访问这个对象。 所以就可能出现这种情况:某个线程在等待另一个线程,而后者又在等待别的线程,这样一直下去,直到这个链条上的线程又在等待第一个线程的释放锁。 你将得到一个线程之间相互等待的连续循环,没有哪个线程能继续。这称之为“死锁”(deadlock)。,26,死锁的四个必要条件: 互斥条件:一个资源每次只能被一个进程使用。 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关
26、系。,27,9.4 总结,线程和进程的区别 线程的优点 JAVA线程的实现 线程的状态和调度 多线程同步问题 死锁,28,9.1 Java中多线程的基本概念,在多线程模型中,多个线程共存于同一块内存中,且共享资源。 每个线程分配有限的时间片来处理任务。由于CPU在各个线程之间的切换速度非常快,用户感觉不到,从而认为并行运行。,29,9.1.1 多线程的特点,多个线程在运行时,系统自动在线程之间进行切换; 由于多个线程共存于同一块内存,线程之间的通信非常容易; Java将线程视为一个对象。线程要么是Thread类的对象,要么是接口Runnable的对象。,30,9.1.1 多线程的特点(续),当
27、多个线程并行执行时,具有较高优先级的线程将获得较多的CPU时间片; 优先级是从1到10的整数,并且它仅表示线程之间的相对关系; 多个线程共享一组资源,有可能在运行时产生冲突。必须采用synchronized关键字协调资源,实现线程同步。,31,9.2.1 多线程编程中常用的常量和方法,线程类Thread定义在java.lang包中; Thread类包含的常量有:,1. public static final int MAX_PRIORITY: 最大优先级,值是10。 2. public static final int MIN_PRIORITY: 最小优先级,值是1。 3. public st
28、atic final int NORM_PRIORITY:缺省优先级,值是5。,32,9.2.1 多线程编程中常用的常量和方法(续),常用方法:,currentThread( ):返回当前运行的线程对象,是一个静态的方法。 sleep(int n):使当前运行的线程睡n个毫秒,然后继续执行,也是静态方法。 yield( ):使当前运行的线程放弃执行,切换到其它线程,是一个静态方法。 isAlive( ):判断线程是否处于执行的状态,返回值true表示处于运行状态,false表示已停止。,33,9.2.1 多线程编程中常用的常量和方法(续),start( ):使调用该方法的线程开始执行。 run
29、( ):该方法由start( )方法自动调用。 stop( ):使线程停止执行,并退出可执行状态。 suspend():使线程暂停执行,不退出可执行态。 resume( ):将暂停的线程继续执行。 setName(String s):赋予线程一个名字。 getName( ):获得调用线程的名字。,34,9.2.1 多线程编程中常用的常量和方法(续),getPriority( ):获得调用线程的优先级。 setPriority(int p):设置线程的优先级。 join( ):等待线程死亡,若中断了该线程, 将抛出异常。,35,9.2.1 多线程编程中常用的常量和方法(续),注意1:在创建线程对
30、象时,缺省的线程优先级是5,一般设置优先级4到6之间,不要设置为10,否则其它线程将执行不到。 注意2:Java的调度器能使高优先级的线程始终运行,一旦CPU有空闲,具有同等优先级的线程,以轮流的方式顺序使用时间片。,36,9.2.2 线程的生命周期,class getThreadInfo / 程序9-1:单线程示例 public static void main(String args ) String name; int p; Thread curr; curr=Thread.currentThread( ); System.out.println(当前线程: +curr); name=c
31、urr.getName( ); p=curr.getPriority( ); System.out.println(线程名: +name); System.out.println(优先级 :+p); ,程序输出结果: 当前线程: Threadmain,5,main 线程名 : main 优先级 :5,39,9.2.3 创建多线程的方法,方法1:通过Thread类的子类实现多线程。 方法2:定义一个实现Runnable接口的类实现多线程。,40,9.2.3 创建多线程的方法(续),方法1:通过创建Thread类的子类实现多线程,步骤如下 :,1. 定义Thread类的一个子类。 2. 定义子类中
32、的方法run( ),覆盖父类中的 方法run( )。 3. 创建该子类的一个线程对象。 4. 通过start( )方法启动线程。例如9-2:,/ 程序9-2 class UserThread extends Thread int sleepTime; public UserThread(String id) / 构造函数 super(id); sleepTime=(int)(Math.random( )*1000); System.out.println(线程名: +getName( )+ ,睡眠: +sleepTime+ 毫秒); ,public void run( ) try / 通过线程
33、睡眠模拟程序的执行 Thread.sleep(sleepTime); catch(InterruptedException e) System.err.println(运行异常: + e.toString( ); System.out.println(运行的线程是:+ getName( ); ,public class multThreadTest public static void main(String args ) UserThreadt1,t2; t1=new UserThread(NO 1); t2=new UserThread(NO 2); t1.start( ); t2.sta
34、rt( ); ,程序某次的运行结果: 线程名: NO 1,睡眠: 885 毫秒 线程名: NO 2,睡眠: 66 毫秒 目前运行的线程是:NO 2 目前运行的线程是:NO 1,注意:Thread类中的run( )方法具有public属性,覆盖该方法时,前面必须带上public。,45,9.2.3 创建多线程的方法(续),方法2:通过接口创建多线程,步骤如下:,1.定义一个实现Runnable接口的类。 2.定义方法run( )。Runnable接口中有一个空的方法run( ),实现它的类必须覆盖此方法。 3.创建该类的一个线程对象,并将该对象作参数,传递给Thread类的构造函数,从而生成Th
35、read类的一个对象。 / 注意这一步! 4.通过start( )方法启动线程。例如9-3:,/ 程序9-3 class UserMultThread implements Runnable int num; UserMultThread(int n) num=n; public void run( ) for(int i=0;i3;i+) System.out.println(运行线程:+num); System.out.println(结束 : +num); ,public class multThreadZero public static void main(String args )
36、 throws InterruptedException Thread mt1=new Thread( new UserMultThread(1); Thread mt2=new Thread( new UserMultThread(2); mt1.start( ); mt2.start( ); mt1.join( ); / 等待线程死亡 mt2.join( ); ,程序运行某次的输出结果: 运行线程:1 运行线程:2 运行线程:1 运行线程:2 运行线程:1 运行线程:2 结束 : 1 结束 : 2,49,9.2.3 创建多线程的方法(续),程序9-3中需要注意的2点: 1. mt1.joi
37、n( )是等待线程死亡,对该方法必须捕捉异常,或通过throws关键字指明可能要发生的异常。 2. 对一个线程不能调用start( )两次,否则会产生IllegalThreadStateException异常。,50,9.3.1 线程调度模型,线程调度程序挑选线程时,将选择处于就绪状态且优先级最高的线程。 如果多个线程具有相同的优先级,它们将被轮流调度。 程序9-4验证了Java对多线程的调度方法。,class threadTest extends Thread / 程序9-4 threadTest(String str)super(str); public void run( ) try T
38、hread.sleep(2); catch(InterruptedException e) System.err.println(e.toString( ); System.out.println(getName( )+ + getPriority( ); ,public class multTheadOne public static void main(String agrs) Thread one=new threadTest(one ); Thread two=new threadTest(two ); Thread three=new threadTest(three ); one.
39、setPriority(Thread.MIN_PRIORITY); two.setPriority(Thread.NORM_PRIORITY); three.setPriority(Thread.MAX_PRIORITY); one.start( ); two.start( ); three.start( ); ,程序输出结果: three 10 two 5 one 1,思考:在run()方法中,通过线程睡眠2个毫秒,模拟程序的执行。如果不睡眠,你知道可能的输出结果是什么吗?为什么?,54,9.3.2 资源冲突,多个线程同时运行虽然可以提高程序的执行效率,但由于共享一组资源,可能会产生冲突,例
40、如程序9-5 。,class UserThread / 程序9-5 void Play(int n) System.out.println(运行线程 NO:+n); try Thread.sleep(3); catch(InterruptedException e) System.out.println(“线程异常, NO:+n); System.out.println(结束线程 NO:+n); ,class UserMultThread implements Runnable UserThread UserObj; int num; UserMultThread(UserThread o,i
41、nt n) UserObj=o; num=n; public void run( ) UserObj.Play(num); ,public class multTheadTwo public static void main(String args ) UserThread Obj=new UserThread( ); Thread t1=new Thread( new UserMultThread(Obj,1); Thread t2=new Thread( new UserMultThread(Obj,2); t1.start( ); t2.start( ); ,程序输出结果: 运行线程 N
42、O:1 运行线程 NO:2 结束线程 NO:1 结束线程 NO:2,59,9.3.3 同步方法,Java通过关键字synchronized实现同步。 当对一个对象(含方法)使用synchronized,这个对象便被锁定或者说进入了监视器。在一个时刻只能有一个线程可以访问被锁定的对象。它访问结束时,让高优先级并处于就绪状态的线程,继续访问被锁定的对象,从而实现资源同步。 加锁的方法有两种:锁定冲突的对象,或锁定冲突的方法。,60,9.3.3 同步方法(续),1. 锁定冲突的对象。语法格式:,synchronized ( ObjRef ) Block / 需要同步执行的语句体 锁定对象可以出现在任
43、何一个方法中。例如,修改程序9-5中的方法run( ) 如下:,public void run( ) synchronized(UserObj) UserObj.Play(num); 运行结果如下: 运行线程 NO:1 结束线程 NO:1 运行线程 NO:2 结束线程 NO:2 运行线程 NO:3 结束线程 NO:3,62,9.3.3 同步方法(续),2. 锁定冲突的方法。语法格式:,synchronized 方法的定义 例如,修改程序9-5中的方法Play( ) 如下: synchronized void Play(int n) / 中间的程序代码略 注意: 1. 对方法run( )无法加锁
44、,不可避免冲突; 2. 对构造函数不能加锁,否则出现语法错误。,63,9.4 线程间通信,多线程通信的方法有两种: 1. 把共享变量和方法封装在一个类中实现; 2. 通过wait( )和notify( )方法实现。,64,9.4.1 通过封装共享变量实现线程通信,程序9-6演示了通过将共享变量封装在一个类中,实现线程通信,class comm /共享类 private int n; private boolean bool=false; void produce(int i) while(bool) n=i; bool=true; System.out.println(n 产生数据:+n);
45、void readout( ) while(!bool) bool=false; System.out.println( 读取数据:+n); ,/ 读取数据类 class dataProducer implements Runnable comm cm; dataProducer(comm c) cm=c; public void run( ) / 生产者产生5个随机数 for(int i=0;i5;i+) duce(int)(Math.random( )*100); ,class dataConsumer implements Runnable comm cm; dataCons
46、umer(comm c) cm=c; public void run( ) for(int i=0;i5;i+) cm.readout( ); / 消费者读取数据 ,public class multTheadThree public static void main(String args ) comm cm=new comm( ); Thread t1=new Thread( /无名对象做参数 new dataProducer(cm); Thread t2=new Thread( new dataConsumer(cm); t1.start( ); t2.start( ); ,程序的某次运行结果: 产生数据:81 读取数据:81 产生数据:15 读取数据:15 产生数据:92 读取数据:92 产生数据:98 读取数据:98 产生数据:79 读取数据:79,70,9.4.2 通过系统方法实现线程通信,线程同步控制的第二种方法是
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 地产游戏活动方案
- 公务员考试活动方案
- 2025至2030年中国仿皮古典吉他包行业投资前景及策略咨询报告
- 2025至2030年中国二氯一氟乙烷行业投资前景及策略咨询报告
- 2025至2030年中国专业无线话筒行业投资前景及策略咨询报告
- 2025至2030年中国三格餐盒行业投资前景及策略咨询报告
- 2025至2030年中国VCD盒模具行业投资前景及策略咨询报告
- 湖北黄冈市英山县事业单位2025年统一公开招聘工作人员笔试历年典型考题及考点剖析附带答案详解
- 旅游英语词汇与口语考试题
- 公司书法比赛策划方案
- 客户拜访跟进管理制度
- 影像科招聘试题及答案
- 湘教版七年级数学下册期末考试卷(附答案和解析)
- 关于中心医院“十五五”发展规划(2025-2030)
- 2025湖南长沙市轨道交通运营限公司招聘372人易考易错模拟试题(共500题)试卷后附参考答案
- 2025智联银行笔试题库及答案
- 法学概论研究方法的试题及答案
- 2025年健康管理师考试试题及答案
- 第六单元不规则或组合图形的周长“拓展型”专项练习-五年级数学下册典型例题(原卷版)苏教版
- 2025年中考化学模拟考试试卷附带答案
- 2024年地理中考模拟考试地理(贵州贵阳卷)(A4考试版)
评论
0/150
提交评论