第22讲 Java高级编程(一).

Slides:



Advertisements
Similar presentations
软件编程基础 一、程序的编辑 Java 源程序是以 Java 为后缀的简单的文本文件,可以用各种 Java 集成开发环境中的源代码编辑器来编写,也可以用其他文 本编辑工具,如 Windows 中的记事本或 DOS 中的 EDIT 软件等。 利用文字编辑器编写下列程序 public class Hello.
Advertisements

Java 程序分类 Java Application :是完整程序,需要独立的解 释器解释运行;以 “.java” 为后缀的文件,以 main() 方法作为程序入口,由 java 编译器编译生 成字节码,由 Java 解释器加载执行字节码。 Java Applet 没有 main() 方法作为程序入口,是嵌在.
面向侧面的程序设计 方林博士 本文下载地址:
单元二:面向对象程序设计 任务二:借书卡程序设计.
第四章 类、对象和接口.
第三讲 面向对象(上).
3.2 Java的类 Java 类库的概念 语言规则——程序的书写规范 Java语言 类库——已有的有特定功能的Java程序模块
JAVA 编 程 技 术 主编 贾振华 2010年1月.
项目6 通用堆栈.
讓你的程式具有多工(Multitasking) 及多重處理(Multiprocessing)的能力
Java Programming Spring, 2010
四資二甲 第三週作業 物件導向程式設計.
第二十章 圖型介面與網路對播 (GUI and Intercross Transition) 20-1 簡介 20-2 ActionListener Interface 20-3 ActionEvent Class 20-4 Vector Class 20-5 圖型介面與視窗關閉 20-6 圖型介面與資料顯示.
第11章 Java多媒体技术.
第二章 JAVA语言基础.
第二部分 Java语言基础篇 第4章 Java语言与面向对象 (之一).
Ch07 介面與多重繼承 物件導向程式設計(II).
C++中的声音处理 在传统Turbo C环境中,如果想用C语言控制电脑发声,可以用Sound函数。在VC6.6环境中如果想控制电脑发声则采用Beep函数。原型为: Beep(频率,持续时间) , 单位毫秒 暂停程序执行使用Sleep函数 Sleep(持续时间), 单位毫秒 引用这两个函数时,必须包含头文件
第10讲 Java面向对象编程基础(4) 教学目标 主要内容.
Ch02 視窗Swing套件 物件導向系統實務.
Ch08 巢狀類別 物件導向程式設計(II).
2.1 基本資料型別 2.2 變數 2.3 運算式與運算子 2.4 輸出與輸入資料 2.5 資料型別轉換 2.6 實例
2018/11/15 面向对象与多线程综合实验-GUI设计 教师:段鹏飞.
例外處理(Exception Handling)
Java语言程序设计 第七部分 多线程.
Java基础 JavaSE异常.
第六章 类的扩展与继承.
西南科技大学网络教育系列课程 高级语程序设计(Java) 第五章 继承、接口与范型.
程式設計實作.
CH09 套件 物件導向程式設計(II).
2018/12/3 面向对象与多线程综合实验-网络编程 教师:段鹏飞.
Java语言程序设计 第五部分 Java异常处理.
Java程序设计 第9章 继承和多态.
辅导课程六.
第10章 Java的线程处理 10.1 线程的基本概念 10.2 线程的属性 10.3 线程组 10.4 多线程程序的开发.
中国矿大计算机学院杨东平 第5章 接口和包 中国矿大计算机学院杨东平
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
第一次课后作业 1. C/C++/Java 哪些值不是头等程序对象 2. C/C++/Java 哪些机制采用的是动态束定
9.1 程式偵錯 9.2 捕捉例外 9.3 自行拋出例外 9.4 自定例外類別 9.5 多執行緒
3.1 数据类型 3.2 标识符与关键字 3.3 常量 3.4 变量 3.5 运算符与表达式 3.6 一个编程实例
第9讲 Java的继承与多态(一) 类的继承 子类的创建 方法覆盖.
本节内容 模拟线程切换 视频提供:昆山滴水信息技术有限公司 官网地址: 论坛地址: QQ交流 :
异常及处理.
Ch02-基礎語法.
CH04 視窗中元件排排坐 物件導向系統實務.
C/C++/Java 哪些值不是头等程序对象
* 單元:電腦與問題解決 主題:Java物件導向程式設計-類別與物件 台南縣國立善化高中 蕭嘉民 老師
Multithread 多執行緒 以GUI為例了解物件以及Event
JAVA 编 程 技 术 主编 贾振华 2010年1月.
《JAVA程序设计》 语音答疑 辅导老师:高旻.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
第二章Java基本程序设计.
$9 泛型基础.
第二章 Java基本语法 讲师:复凡.
分裂对象模型 C++ otcl.
Java程式初體驗大綱 大綱 在學程式之前及本書常用名詞解釋 Hello Java!程式 在Dos下編譯、執行程式
信号量(Semaphore).
第二章 Java语法基础.
西南科技大学网络教育系列课程 高级语程序设计(Java) 第八章 线程.
第二章 Java基本语法 讲师:复凡.
Chapter 18 使用GRASP的对象设计示例.
C++语言程序设计 C++语言程序设计 第八章 继承 C++语言程序设计.
辅导课程十五.
第二章 Java基本语法 讲师:复凡.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
JAVA 程式設計與資料結構 第三章 物件的設計.
创建、启动和关闭Activity 本讲大纲: 1、创建Activity 2、配置Activity 3、启动和关闭Activity
使用Fragment 本讲大纲: 1、创建Fragment 2、在Activity中添加Fragment
第二章 Java基础语法 北京传智播客教育
Summary
Presentation transcript:

第22讲 Java高级编程(一)

教学目标 理解多线程程序设计的基本思想 掌握多线程的实现和线程的同步与控制 理解Java网络编程的基本思想 掌握基于Socket的低层Java网络编程与基于UDP的Java网络编程,以及基于无连接的数据报通信编程 理解JDBC的基本思想 掌握数据源的建立和数据库的访问

多线程程序设计 支持多线程——Java可以让不同的程序块同时运行,可以达到处理多任务的目的。 所谓的线程(thread)是指程序的运行流程,多线程的技术使单个程序内部也可以在同一时刻执行多个代码段,完成不同的任务,这种机制称为多线程。 Java语言利用多线程实现了一个异步的执行环境。例如,在一个网络应用程序里,可以在后台运行一个下载网络数据的线程,在前台则运行一个线程来显示当前下载的进度,以及一个用于处理用户输入数据的线程。 Java多线程机制是通过Java类包java.lang中的类Thread实现的,Thread类封装了对线程控制所必需的方法。

单线程实现示例 class ST extends Thread{ public ST(String str){ super(str); } public void run() { String B[] = {"起床","早饭","上班","下班"}; String S[] = {"备课","上课","布置作业","下课"}; String Name = null; Name = getName(); for(int i = 0;i<4;i++) { if(Name.equals("B")){ System.out.println(Name+":"+B[i]); try{ sleep((long)(Math.random()*1000)); }catch(InterruptedException e){} } if(Name.equals("S")){ System.out.println(Name+":"+S[i]); try { sleep((long)(Math.random()*1000)); } } }} 单线程实现示例

单线程实现示例(续) 运行结果: B:早饭 B:上班 B:下班 S:备课 S:上课 S:布置作业 S:下课 public class Ex12_1 { public static void main(String args[]) ST s1 = new ST("B"); ST s2 = new ST("S"); s1.run(); s2.run(); } 程序分析: try块中sleep()方法只是简单地告诉线程休息多少毫秒,其参数为休息时间。当这个时间过去后,线程即可继续执行。当某个线程睡眠时,sleep()并不占用系统资源,其他某一线程可继续工作。

多线程的实现 单线程的限制——要运行s2.run()方法,一定要等到s1.run()运行完毕才行。 实现多线程的方法: 在类里激活线程 此类必须是扩展自Thread类,extends Thread 线程的处理必须编写在run()方法内。 run()方法是定义在Thread类中的一个方法。 使用接口实现多线程

多线程实现示例 class ST extends Thread{ public ST(String str) { super(str); } public void run() { String B[] = {"起床","早饭","上班","下班"}; String S[] = {"备课","上课","布置作业","下课"}; String Name = null; Name = getName(); for(int i = 0;i<4;i++) { if(Name.equals("B")) { System.out.println(Name+":"+B[i]); try { sleep((long)(Math.random()*1000)); }catch(InterruptedException e){} } if(Name.equals("S")) { System.out.println(Name+":"+S[i]); try { sleep((long)(Math.random()*1000)); } } }} 多线程实现示例

多线程实现示例(续) public class Ex12_2{ public static void main(String args[]) { new ST("B").start(); new ST("S").start(); } 运行结果: 第一次运行 第二次运行 第三次运行 B:起床 B:起床 B:起床 S:备课 S:备课 S:备课 S:上课 B:早饭 S:上课 S:布置作业 S:上课 B:早饭 B:早饭 B:上班 B:上班 S:下课 S:布置作业 B:下班 B:上班 B:下班 S:布置作业 S:下班 S:下课 S:下课 程序分析: 程序中的main()方法中构 造了两个ST类的线程,一个称 为“B”线程“,另一个称为“S”线 程,并调用了start()方法来启 动这两个线程。这两个线程同时运行,并且同时显示输出,且这两个线程的输出次序是随机的。

使用接口实现多线程 如果类本身已经继承了某个父类,现在又要继承Thread类来创建线程,就违背了Java不支持多继承的原则,解决这个问题的方法是使用接口。 实现接口Runnable。Runnable接口里声明了抽象的run() 方法,把处理线程的程序代码放在run()里就可以创建线程了。 创建一个程序实现当前时间显示,要求每2秒显示1次,显示20次后程序退出。 分析:在Java的java.util包中有一个Date类,可以通过实例化一个Date对象得到当前时间。要求每两秒显示一次时间,线程是完成这个任务最好的角色。通过每两秒唤醒线程一次,并且就在这一瞬间显示出时间。还需设置一个循环控制输出次数。

使用接口实现多线程示例 import java.util.Date; public class Ex12_3 implements Runnable{ private Thread clock = null ;private Date nowtime = new Date(); public Ex12_3(){clock = new Thread(this);clock.start();} public void run(){ while(true){ nowtime = new Date(); System.out.println(nowtime); try{clock.sleep(2000); } catch(InterruptedException ie) {System.err.println("Thread error: " + ie);} } public static void main(String args[]){ Ex12_3 time = new Ex12_3();

使用接口实现多线程示例(续) 运行结果: Sat Feb 10 10:51:37 CST 2007 Sat Feb 10 10:51:39 CST 2007 Sat Feb 10 10:51:41 CST 2007 Sat Feb 10 10:51:43 CST 2007 Sat Feb 10 10:51:45 CST 2007 Sat Feb 10 10:51:47 CST 2007 Sat Feb 10 10:51:49 CST 2007 Sat Feb 10 10:51:51 CST 2007 Sat Feb 10 10:51:53 CST 2007 Sat Feb 10 10:51:55 CST 2007 Sat Feb 10 10:51:57 CST 2007 Sat Feb 10 10:51:59 CST 2007 Sat Feb 10 10:52:01 CST 2007 Sat Feb 10 10:52:03 CST 2007 Sat Feb 10 10:52:05 CST 2007 Sat Feb 10 10:52:07 CST 2007 Sat Feb 10 10:52:09 CST 2007 Sat Feb 10 10:52:11 CST 2007 Sat Feb 10 10:52:13 CST 2007 Sat Feb 10 10:52:15 CST 2007 程序分析: 通过Thread类的构造方法创建clock线程并进行初始化,同时将Ex12_3类的当前对象(this)作为参数。该参数将clock线程的run()方法与Ex12_3类实现runnable接口的run()方法联系在一起,因此,当线程启动后,Java类的run()方法就开始执行。

多线程同步示例 运行结果: sum=100 sum=200 sum=300 public class Ex12_4{ public static void main(String args[]) { Cperson c1 = new Cperson(); Cperson c2 = new Cperson(); c1.start(); c2.start(); } } class Countmoney { private static int sum=0; public static void add(int n) { int t = sum; t = t + n; try{ Thread.sleep((int)(1000*Math.random()));} catch(InterruptedException e){} sum = t; System.out.println("sum="+sum); }} class Cperson extends Thread{ public void run() { for(int i = 1;i<=3;i++) Countmoney.add(100); 运行结果: sum=100 sum=200 sum=300

多线程同步示例 程序分析: 输出结果不正确。其错误原因在于两个线程在各自run()方法还没结束前,另一个线程已开始激活,因此造成计算上的错误。 要更正这个错误,只要设置c1线程处理完之后,接着处理c2线程就可以了。在aad()方法之前加上synchronized关键字,使其成为同步方法。 public synchronized static void add(int n){…… } class Cperson extends Thread { public void run() { for(int i = 1;i<=3;i++) Countmoney.add(100); }

实现多线程同步 ——synchronized 为了避免资源冲突,Java使用关键字synchronized使方法通信同步,在同一时间内,一个方法只能有一个线程运行。 在本例中,可以学到同步处理的重要性。如有多个线程共享一个变量时,特别要注意它们之间的访问顺序,否则一个线程未处理完某个方法时,另一个线程又进来,就有可能发生错误。

线程的四种状态 每一个线程,一般有四种状态:创建、运行、阻塞与消亡。这四种状态均可通过Thread类所提供的方法来控制。线程状态的转移与方法之间的关系如图12-1所示。 线程在产生时便进入创建状态。即new Thread()创建对象时,线程所处的便是这个状态,但此时系统并不会分配资源,直到用start()方法激活线程时才会分配。 当start()方法激活线程时,线程进入可运行的状态。此时最先抢到CPU资源的线程先开始运行start()方法,其余的线程在队列中等待机会争取CPU的资源,一旦争取到就开始运行。

线程状态转换图 图12-1 线程状态的转移与方法之间的关系

线程的四种状态的转换过程 当发生下列事件之一时,线程就进入阻塞状态。 1.该线程调用对象的wait()方法; 2.该线程本身调用sleep()方法。sleep(long millis)可用来设置睡眠的时间。 3.该线程和另一个线程join()在一起时。当某一线程调用join()时,则其他尚未激活的线程或程序代码会等到该线程结束后才会开始运行。 当线程被阻塞后,便停止run()方法的运行,直到被阻塞的原因不存在后,线程回到可运行状态,继续排队争取CPU的资源。

线程的状态转换 线程被阻塞情形消失的原因有下列几点: 1.如果线程是由调用对象的wait()方法所阻塞,则该对象的notify()方法被调用时可解除阻塞。notify()方法用来“通知”被wait()阻塞的线程开始运行。 2.线程进入睡眠状态,但指定的睡眠时间到了。 当线程的run()方法结束,或是线程调用它的stop()时,则线程进入消亡的状态。 利用上述方法可以完成线程间的通信以及线程状态之间的转换,下面举例说明通过wait()、notify()来达到线程间的通信和状态的转换。

线程间通信示例 例12_5 线程间通信的示例。本例模拟两个银行之间的转帐业务,当A银行转帐给B银行后,暂停转帐,通知B银行转帐给A银行,转帐金额随机确定,源代码如下。 import java.awt.*; import java.awt.event.*; public class Ex12_5 extends Frame { protected static final String[] NAMES = {"A","B"}; private int accounts[] = {1000,1000}; private TextArea info = new TextArea(5,40); private TextArea status = new TextArea(5,40);

线程间通信示例(续) public Ex12_5(){ super("Ex12_5");setLayout(new GridLayout(2,1)); add(makePanel(info,"Accounts")); add(makePanel(status,"Threads")); validate();pack();setVisible(true); Ex12_5Thread A = new Ex12_5Thread(0,this,status); Ex12_5Thread B = new Ex12_5Thread(1,this,status); addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent we) {System.exit(0);} });}

线程间通信示例(续) public synchronized void transfer(int from,int into,int amount){ info.append("\nAccount A: $" + accounts[0]); info.append("\tAccount B: $" + accounts[1]); info.append("\n=> $" + amount + " from " + NAMES[from] + " to " + NAMES[into]); while(accounts[from] < amount){ try{wait();}catch(InterruptedException ie){System.err.println("Error: " + ie);} } accounts[from] -= amount;accounts[into] +=amount;notify(); private Panel makePanel(TextArea text,String title){ Panel p = new Panel(); p.setLayout(new BorderLayout()); p.add("North",newLabel(title)); p.add("Center",text);return p; public static void main(String args[]){ Ex12_5 bank = new Ex12_5(); }} public static void main(String args[]) {Ex12_5 bank = new Ex12_5();}

线程间通信示例(续) class Ex12_5Thread extends Thread{ private Ex12_5 bank; private int id; private TextArea display; public Ex12_5Thread(int _id,Ex12_5 _bank,TextArea _display){ bank = _bank;id = _id;display = _display;start(); } public void run(){ while(true){int amount = (int)(900*Math.random()); display.append("\nThread " + Ex12_5.NAMES[id] + " sends $ " + amount + " into " + Ex12_5.NAMES[(1-id)]); try{sleep(50); }catch(InterruptedException ie){ System.err.println("Interrupted"); bank.transfer(id,1-id,amount);

线程间通信示例(续) 图12-1 运行结果 程序分析: 程序中创建一个银行类Ex12_5,一个整型数组域accounts[]给两个银行初始化银行账户金额,然后在其构造方法中创建两个银行客户线程A和B。这个程序中最重要的方法是transfer(),它是同步方法。它需要三个参数:取钱的账号,存钱的账号,转帐的金额。在转帐之前检查相应账号是否有足够的资金,然后在转帐之后计算新的余额。这个方法被每个银行共享,因此必须设计为同步方法,在一个银行使用时,这个方法被加锁,不再使用时,自动解锁,其他银行可以使用这个方法。 程序中使用了方法start()、sleep()、run()、notify()和wait(),请分析它们在程序中的作用,并理解运行顺序。 如果将上例中int amount = (int)(900*Math.random());中900换成1500后运行结果会怎样? 图12-1 运行结果