第7章 Java多线程Word格式文档下载.docx

上传人:b****2 文档编号:4011221 上传时间:2023-05-02 格式:DOCX 页数:31 大小:45.17KB
下载 相关 举报
第7章 Java多线程Word格式文档下载.docx_第1页
第1页 / 共31页
第7章 Java多线程Word格式文档下载.docx_第2页
第2页 / 共31页
第7章 Java多线程Word格式文档下载.docx_第3页
第3页 / 共31页
第7章 Java多线程Word格式文档下载.docx_第4页
第4页 / 共31页
第7章 Java多线程Word格式文档下载.docx_第5页
第5页 / 共31页
第7章 Java多线程Word格式文档下载.docx_第6页
第6页 / 共31页
第7章 Java多线程Word格式文档下载.docx_第7页
第7页 / 共31页
第7章 Java多线程Word格式文档下载.docx_第8页
第8页 / 共31页
第7章 Java多线程Word格式文档下载.docx_第9页
第9页 / 共31页
第7章 Java多线程Word格式文档下载.docx_第10页
第10页 / 共31页
第7章 Java多线程Word格式文档下载.docx_第11页
第11页 / 共31页
第7章 Java多线程Word格式文档下载.docx_第12页
第12页 / 共31页
第7章 Java多线程Word格式文档下载.docx_第13页
第13页 / 共31页
第7章 Java多线程Word格式文档下载.docx_第14页
第14页 / 共31页
第7章 Java多线程Word格式文档下载.docx_第15页
第15页 / 共31页
第7章 Java多线程Word格式文档下载.docx_第16页
第16页 / 共31页
第7章 Java多线程Word格式文档下载.docx_第17页
第17页 / 共31页
第7章 Java多线程Word格式文档下载.docx_第18页
第18页 / 共31页
第7章 Java多线程Word格式文档下载.docx_第19页
第19页 / 共31页
第7章 Java多线程Word格式文档下载.docx_第20页
第20页 / 共31页
亲,该文档总共31页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

第7章 Java多线程Word格式文档下载.docx

《第7章 Java多线程Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《第7章 Java多线程Word格式文档下载.docx(31页珍藏版)》请在冰点文库上搜索。

第7章 Java多线程Word格式文档下载.docx

(1)扩展Thread类。

(2)实现Runnable接口。

7.3.1扩展Thread类

要创建线程,首先定义一个Thread类的子类,在该类中重写thread类的run()方法,即定义线程所需完成的工作。

Thread类常用的构造方法如下:

publicThread():

创建新的Thread对象;

publicThread(Stringname):

分配名字为name的新thread对象。

Thread类常用的方法如下:

publicstaticvoidsleep(longmillis)throwsinterruptedException:

在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。

publicvoidstart():

使该线程开始执行;

Java虚拟机调用该线程的run()方法。

publicvoidrun():

定义该线程需执行的任务。

publicfinalStringgetName():

返回该线程的名称。

publicfinalBooleanisAlive():

测试线程是否处于活动状态。

如果线程已经启动且尚未终止,则为活动状态。

publicstaticThreadcurrentThread():

返回当前正在执行的线程对象的引用。

【例7-1】通过扩展thread类的方法创建线程示例。

1publicclassTestMitiThread{

2publicstaticvoidmain(String[]args){

3System.out.println(Thread.currentThread().getName()+"

线程运行开始!

"

);

4newMitiSay("

A"

).start();

5newMitiSay("

B"

6System.out.println(Thread.currentThread().getName()+"

线程运行结束!

7}

8}

9classMitiSayextendsThread{

10publicMitiSay(StringthreadName){

11super(threadName);

12}

13publicvoidrun(){

14System.out.println(getName()+"

15for(inti=0;

i<

10;

i++){

16System.out.println(i+"

"

+getName());

17try{

18sleep((int)Math.random()*1000);

19}catch(InterruptedExceptione){

20e.printStackTrace();

21}

22}

23System.out.println(getName()+"

24}

25}

程序运行结果:

D:

\java\7>

javacExample7_1.java

javaExample7_1

main线程运行开始!

A线程运行开始!

0A

main线程运行结束!

B线程运行开始!

1A

0B

2A

1B

3A

2B

4A

5A

4B

6A

5B

7A

6B

8A

7B

9A

8B

A线程运行结束!

9B

B线程运行结束!

程序说明:

(1)程序启动运行main时候,java虚拟机启动一个进程,主线程main在main()调用时候被创建。

随着调用MitiSay的两个对象的start方法,另外两个线程也启动了,这样,整个应用就在多线程下运行。

(2)在一个方法中调用Thread.currentThread().getName()方法,可以获取当前线程的名字。

在mian方法中调用该方法,获取的是主线程的名字。

(3)start()方法的调用后并不是立即执行多线程代码,而是使得该线程变为可运行态(Runnable),什么时候运行是由操作系统决定的。

从程序运行的结果可以发现,多线程程序是乱序执行。

因此,只有乱序执行的代码才有必要设计为多线程。

(4)Thread.sleep()方法调用目的是不让当前线程独自霸占该进程所获取的CPU资源,以留出一定时间给其他线程执行的机会。

实际上所有的多线程代码执行顺序都是不确定的,每次执行的结果都是随机的。

7.3.2实现runnable接口

上一节介绍了通过继承thread类创建线程的方法,现在再来介绍另一种创建线程的方法:

实现runnable接口。

在面向对象一章中,我们已经知道,在Java语言中只支持单继承,当所定义的线程类已经是某个类的子类,此时继承thread类创建线程的方法就行不通了,必须采用这一节的方法:

实现runnable接口创建线程。

实现runnable接口需要引用thread类的另一种构造方法:

PublicThread(Runnabletarget):

分配新的Thread对象。

【例7-2】通过实现runnable接口的方法创建线程。

1publicclassTestMitiThread1implementsRunnable{

2publicstaticvoidmain(String[]args){

3System.out.println(Thread.currentThread().getName()+"

4TestMitiThread1test=newTestMitiThread1();

5Threadthread1=newThread(test);

6Threadthread2=newThread(test);

7thread1.start();

8thread2.start();

9System.out.println(Thread.currentThread().getName()+"

10}

11publicvoidrun(){

12System.out.println(Thread.currentThread().getName()+"

13for(inti=0;

14System.out.println(i+"

+Thread.currentThread().getName());

15try{

16Thread.sleep((int)Math.random()*10);

17}catch(InterruptedExceptione){

18e.printStackTrace();

19}

20}

21System.out.println(Thread.currentThread().getName()+"

23} 

 

Thread-0线程运行开始!

0Thread-0

Thread-1线程运行开始!

0Thread-1

1Thread-1

1Thread-0

2Thread-0

2Thread-1

3Thread-0

3Thread-1

4Thread-0

4Thread-1

5Thread-0

6Thread-0

5Thread-1

7Thread-0

8Thread-0

6Thread-1

9Thread-0

7Thread-1

Thread-0线程运行结束!

8Thread-1

9Thread-1

Thread-1线程运行结束!

(1)TestMitiThread1类通过实现Runnable接口,使得该类有了多线程类的特征。

run()方法是多线程程序的一个约定。

所有的多线程代码都在run方法里面。

Thread类实际上也是实现了Runnable接口的类。

(2)在启动的多线程的时候,需要先通过Thread类的构造方法Thread(Runnabletarget)构造出对象,然后调用Thread对象的start()方法来运行多线程代码。

(3)实际上所有的多线程代码都是通过运行Thread的start()方法来运行的。

因此,不管是扩展Thread类还是实现Runnable接口来实现多线程,最终还是通过Thread的对象的API来控制线程的,熟悉Thread类的API是进行多线程编程的基础。

7.3.3两种创建线程方法的比较

(1)扩展thread类

该方法较简单,采用了Java面向对象的继承机制,但有碍于Java语言只支持单继承的特点,使用比较单一,有很大的局限性。

在继承了thread后,不能再继承其他类。

(2)实现runnable接口

该方法采用实现接口的方式,具有很好的灵活型。

既避免了Java单继承性带来的局限,又适合多个相同程序代码的线程去处理统一资源的情况,实现了资源共享。

【例7-3】Thread类创建线程模拟铁路售票系统的差异演示。

说明:

该系统有四个售票点,发售某日某次列车的10张车票。

要求:

一个售票点用一个线程表示。

1publicclassExample7_3{

2publicstaticvoidmain(String[]agrs){

3newThreadTest().start();

4newThreadTest().start();

5newThreadTest().start();

6newThreadTest().start();

7}

8}

9classThreadTestextendsThread{

10privateintticket=10;

11publicvoidrun(){

12while(true){

13if(ticket>

0){

14System.out.println(Thread.currentThread().getName()+"

isselling15ticket"

+ticket--);

15}

16else{

17break;

18}

19}

20}

21}

javacExample7_3.java

javaExample7_3

Thread-0issellingticket10

Thread-0issellingticket9

Thread-1issellingticket10

Thread-0issellingticket8

Thread-0issellingticket7

Thread-2issellingticket10

Thread-3issellingticket10

Thread-2issellingticket9

Thread-0issellingticket6

Thread-1issellingticket9

Thread-0issellingticket5

Thread-2issellingticket8

Thread-3issellingticket9

Thread-2issellingticket7

Thread-0issellingticket4

Thread-1issellingticket8

Thread-0issellingticket3

Thread-2issellingticket6

Thread-3issellingticket8

Thread-2issellingticket5

Thread-2issellingticket4

Thread-2issellingticket3

Thread-2issellingticket2

Thread-2issellingticket1

Thread-0issellingticket2

Thread-1issellingticket7

Thread-0issellingticket1

Thread-3issellingticket7

Thread-1issellingticket6

Thread-1issellingticket5

Thread-1issellingticket4

  从结果上看每个票号都被打印了四次,即四个线程各自卖各自的10张票,而不去卖共同的10张票。

这种情况是怎么造成的呢?

我们需要的是,多个线程去处理同一个资源,一个资源只能对应一个对象,在上面的程序中,我们创建了四个ThreadTest对象,就等于创建了四个资源,每个资源都有10张票,每个线程都在独自处理各自的资源。

  经过这些实验和分析,可以总结出,要实现这个铁路售票程序,我们只能创建一个资源对象,但要创建多个线程去处理同一个资源对象,并且每个线程上所运行的是相同的程序代码。

【例7-4】利用接口创建线程模拟铁路售票系统的差异演示。

1publicclassThreadDemo2{

2publicstaticvoidmain(String[]args){

3ThreadTestt=newThreadTest();

4newThread(t).start();

5newThread(t).start();

6newThread(t).start();

7newThread(t).start();

8}

9}

10classThreadTestimplementsRunnable{

11privateinttickets=10;

12publicvoidrun(){

13while(true){

14if(tickets>

0){

15System.out.println(Thread.currentThread().getName()+

16"

issalingticket"

+tickets--);

17}

18}

19}

20}

javacExample7_4.java

javaExample7_4

Thread-3issellingticket6

Thread-1issellingticket2

上面的程序中,创建了四个线程,每个线程调用的是同一个ThreadTest对象中的run()方法,访问的是同一个对象中的变量(tickets)的实例,这个程序满足了我们的需求。

在Windows上可以启动多个记事本程序一样,也就是多个进程使用同一个记事本程序代码。

7.4线程的生命周期及调度

在java中每个线程都要经历五种状态:

新建,就绪,运行,阻塞和死亡。

线程从新生到死亡的状态变化过程称为生命周期。

下面结合图7-1来说明线程的生命周期。

执行完毕

解除阻塞

导致阻塞的事件

start()

调度

图7-1线程的生命周期

新建状态:

使用new创建线程对象,但此时线程并未执行。

就绪状态:

当线程对象调用了start方法以后,线程就处于就绪状态,JAVA虚拟机会为其创建方法调用栈和程序计数器,处于这个状态的线程并没有运行,只是表示可以运行而已。

启动线程使用start方法,而不是run方法,调用start方法来启动线程,系统会把该run方法当成线程执行体来处理,但如果直接调用线程对象的run方法,则run方法会被立即执行,而且在run方法之前的其他线程无法并行执行。

运行状态:

当线程处于就绪状态获得CPU,就开始执行run方法,程序进入运行状态。

一条线程开始运行以后,不可能一直处于运行状态,线程运行状态过程中也会被中断,目的是给其他线程获得执行的机会。

系统会给每个可执行的线程一小段时间来处理任务。

阻塞状态:

当发生如下情况,线程会进入阻塞状态:

1.线程调用sleep方法主动放弃所占用的资源。

2.线程调用了一个阻塞式IO方法,在该方法返回以前,该线程阻塞。

3.线程试图获得一个同步监视器,但该同步监视器正被别的线程所持有。

4.线程在等待某个通知。

5.线程调用了suspend方法将该线程挂起。

终止状态:

1.线程的run方法执行完成,线程正常结束。

2.线程抛出一个未捕获的exception或error。

3.直接调用线程的stop方法来结束该线程。

为了测试某线程是否已经死亡,可以调用线程的isAlive()方法,当线程处于就绪,运行,阻塞的时候返回true,当线程处于新建和死亡状态,该方法返回false。

当对已经死亡的线程调用start方法,会抛出illegalThreadStateException异常。

7.5线程的终止

有三种方法可以终止线程。

1.使用退出标志终止线程

当run方法执行完后,线程就会退出,但有时run方法时永远不会结束的,如在服务器程序中使用线程进行监听客户端请求,或是其他的需要循环处理的任务。

在这种情况下,一般是将这些任务放在一个循环中,如while循环。

想使while循环在某一特定条件下退出,最直接的方法就是设计一个boolean类型的标志,并通过设置这个标志为true或false来控制while循环是否退出。

【例7-5】线程终止示例。

1publicclassExample7_5extendsThread{

2publicbooleanexit=false;

3publicvoidrun(){

4while(!

exit);

5}

6publicstaticvoidmain(String[]args)throwsException{

7Example7_5thread=newExample7_5();

8sleep(5000);

9thread.join();

10System.out.println("

线程退出!

11}

12}

javacExample7_5.java

javaExample7_5

程序分析:

在上面代码中定义了一个退出exit,当exit为true时,while循环退出,exit的默认值为false。

2.使用stop方法终止线程

使用stop方法可以强行终止正在运行或挂起的线程。

我们可以使用如下的代码来终止线程:

Thread.stop();

虽然使用上面的代码可以终止线程,但使用stop方法是很危险的,就像突然关闭计算机电源,而不是按正常程序关机一样,可能会产生不可预料的结果,因此,并不推荐使用stop方法来终止线程。

3.使用interrupt方法终止线程

使用interrupt方法来终止线程可分为两种情况:

(1)线程处于阻塞状态,如使用了sleep方法

(2)使用while(!

isInterrupted()){…}来判断线程是否被中断。

在第一种情况下使用interrupt方法,sleep方法将抛出一个InterruptedException异常,而在第二种情况下线程将直接退出

7.6线程同步

7.6.1线程同步问题

线程同步是为了防止多个线程同时访问一个数据对象时,对数据造成的破坏。

例如,一个线程可能尝试从一个文件中读取数据,而另一个线程则尝试在同一文件

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 总结汇报 > 学习总结

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2