Java语言10 多线程

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

Java语言程序设计资源与环境科学学院第十章多线程进程和线程—在多任务系统中,每个独立执行的程序称为进程。操作系统一般都是多任务的,即能够同时执行多个应用程序。操作系统负责对CPU等设备的资源进行分配和管理,虽然这些设备某一时刻只能做一件事,但以非常小的时间间隔交替执行多个程序,就可以给人以同时执行多个程序的感觉。—一个进程中又可以包含一个或多个线程,一个线程就是一个程序内部的一条执行线索,是被系统独立调度和分派的基本单位。如果在一程序中实现多段代码同时交替运行,就需产生多个线程,并指定每个线程上所要运行的程序代码段,这就是多线程。单线程与多线程ThreadDemo1.Main()ThreadDemo1.run()ThreadDemo1.Main()ThreadDemo1.run()单线程多线程单线程示例publicclassThreadDemo1{publicstaticvoidmain(Stringargs[]){newTestThread().run();while(true){System.out.println(main()function:+Thread.currentThread().getName());}}}classTestThread{publicvoidrun(){while(true){System.out.println(run()function:+Thread.currentThread().getName());}}}多线程示例publicclassThreadDemo1{publicstaticvoidmain(Stringargs[]){newTestThread().start();//创建一个线程对象,start()启动一个线程while(true){System.out.println(main()function:+Thread.currentThread().getName());}}}classTestThreadextendsThread{publicvoidrun(){while(true){System.out.println(run()function:+Thread.currentThread().getName());}}}用Thread类创建线程—要将一段代码在一个新的线程上运行,该代码应该在一个类的run()函数中,并且run()函数所在的类是Thread类的子类。即,我们要实现多线程,必须编写一个继承了Thread类的子类,子类要覆盖Thread类中的run()函数,在子类的run()中调用想在新线程上运行的程序代码。—启动一个新的线程,不是直接调用Thread子类对象的run方法,而是调用Thread子类对象的start()方法。Thread类对象的start()方法产生一个新线程,并执行在该线程上run()方法。—由于线程的代码段在run()中,那么该方法执行完成以后线程也就相应的结束了,因而我们可以通过控制run方法中循环条件来控制线程的结束。多线程注意问题—使用多线程不会增加CPU的能力。但是如果使用JVM的本地线程实现,则不同的线程可以在不同的处理器上同时运行(在多CPU的机器中),从而使多CPU机器得到充分利用。—当应用程序必须等待缓慢的资源(如网络连接或数据库连接)时,或者当应用程序是非交互式的时,多线程通常是有利的。—基于Internet的软件有必要是多线程的,否则用户将感觉应用程序反映迟钝。当开发要支持大量客户机的服务器时,多线程可以使编程较为容易。每个线程可为不同的客户或客户组服务,从而缩短了响应时间。后台线程—如果对某个线程对象在启动(调用start方法)之前调用了setDaemon(true)方法,这个线程就变成了后台线程—对java程序来说,一个进程中只要还有一个前台线程在运行,这个进程就不会结束。如果进程中只有后台线程运行,这个进程就会结束。后台线程示例publicclassThreadDemo3{publicstaticvoidmain(Stringargs[]){Threadtt=newTestThread3();tt.start();}}}classTestThread3extendsThread{publicvoidrun(){while(true){System.out.println(run()function:+Thread.currentThread().getName());}}}tt.setDaemon(true);//设置为后台线程//有一个前台线程,程序不结束程序很快结束Thread的构造函数—publicThread(Runnabletarget)其中Runnable是一个接口,里面只有一个run()方法线程示例publicclassThreadDemo4{publicstaticvoidmain(Stringargs[]){Threadtt=newThread(newTestThread4());//带参数的构造函数tt.start();}}classTestThread4implementsRunnable//实现Runable接口{publicvoidrun(){while(true){System.out.println(run()function:+Thread.currentThread().getName());}}}线程示例—带参数的Thread构造函数和不带参数的Thread构造函数区别。—思考:模拟铁路的售票系统,有四个售票点在某日同时售出某趟列车的100张票。应该如何编写程序?线程示例publicclassThreadTrain{publicstaticvoidmain(Stringargs[]){newTestThread().start();//不带参数的Thread()构造函数newTestThread().start();newTestThread().start();newTestThread().start();}}classTestThreadextendsThread//继承类的方式{inttickets=100;//记录100张票publicvoidrun(){while(true){if(tickets0)System.out.println(Thread.currentThread().getName()+issalingticket+tickets--);}}}创建了4个线程,每个线程都有独立的100张票,显然不合理。线程示例publicclassThreadRain{publicstaticvoidmain(Stringargs[]){TestThreadtt=newTestThread();tt.start();tt.start();//是否能启动多线程?tt.start();tt.start();}}classTestThreadextendsThread//继承类的方式{inttickets=100;//记录100张票publicvoidrun(){while(true){if(tickets0)System.out.println(Thread.currentThread().getName()+issalingticket+tickets--);}}}只有一个线程在运行,并没有多个线程,也是不正确的。线程示例publicclassThreadRain{publicstaticvoidmain(Stringargs[]){TestThreadtt=newTestThread();newThread(tt).start();//创建Runnable参数的Thread构造函数newThread(tt).start();newThread(tt).start();newThread(tt).start();}}classTestThreadimplementsRunnable//采用接口继承方式{inttickets=100;//记录100张票publicvoidrun(){while(true){if(tickets0)System.out.println(Thread.currentThread().getName()+issalingticket+tickets--);}}}只能创建包含100张票的一个资源对象,但是要创建多个线程处理这一个资源对象。使用Runnable接口—适合多个相同程序代码的线程去处理同一资源的情况,把虚拟CPU(线程)同程序的代码、数据有效分离,较好地体现了面向对象的设计思想—可以避免由于Java的单继承特性带来的局限。我们经常碰到这样一种情况,即当我们要将已经继承了某一个类的子类放入多线程中,由于一个类不能同时有两个父类,所以不能用继承Thread类的方式,那么,这个类就只能采用实现Runnable—事实上,几乎所有多线程应用都可用Runnable接口方式。多线程应用—网络聊天程序的收发开始从键盘上读取数据将从键盘上读到的数据发送给对方读取对方回送的数据并加以处理循环线程1从键盘上读取数据将从键盘上读到的数据发送给对方循环线程2读取收到的数据并加以处理单线程情况多线程情况多线程的同步—线程安全在上例中当tickets=5时,打印出“tickets=5”,还没来得及运行“tickets--”,CPU切换到另一个线程上,则另一个线程也打印出“tickets=5”,出现线程同步问题。必须当一个线程中要执行的代码运行完毕后,才能运行另一个线程的代码。这也称为多线程同步问题。线程示例publicclassThreadRain{publicstaticvoidmain(Stringargs[]){TestThreadtt=newTestThread();newThread(tt).start();//创建Runnable参数的Thread构造函数……}}classTestThreadimplementsRunnable//采用接口继承方式{inttickets=100;Stringstr=newString(“”);//任意创建一个对象,synchronized需要publicvoidrun(){while(true){synchronized(str){//增加synchronized语句进行同步控制if(tickets0)System.out.println(Thread.currentThread().getName()+issalingticket+tickets--);}}}}多线程的同步—最简单的同步是将一个方法标记为synchronized,对同一个实例来说,任一时刻只能有一个synchronized方法在执行。当一个方法正在执行某个synchronized方法时,其他线程如果想要执行这个实例的任意一个synchronized方法,都必须等待当前执行synchronized方法的线程退出此方法后,才能依次执行。线程示例publicclassThreadRain{publicstaticvoidmain(Stringargs[]){TestThreadtt=newTestThread();newThread(tt).start();//创建Runnable参数的Thread构造函数……}}classTestThreadimplementsRunnable//采用接口继承方式{inttickets=100;publicvoidrun(){while(true){sell();}}publicsynchronizedvoidsell(){if(tickets0)System.out.println(Thread.currentThread().getName()+issalingticket+tickets--);}}多线程的常见问题—在线程化的程序中,可能发现某些常见而不好的情况是死锁、活锁和资源耗尽

1 / 25
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功