基于《java2实用教程》的java知识点复习整理【第十二章——第十五章】
public class Student {
public static void main(String[] args) {
new Thread(new TalkSend(7777,"localhost",9999)).start();
new Thread(new TalkReceive(8888,"老师")).start();
}
}
第十二章——java多线程机制
一、知识结构框架


二、知识点详解
(一)相关基础概念
1、进程与线程
程序:程序是一段静态的代码
进程:进程是程序(一段代码)的一次动态执行过程
线程:线程是更小的执行单位,是进程执行过程中其中的执行线索
2、主线程与多线程
主线程:即main线程,当JVM加载代码发现main方法后,会启动一个线程,该线程为主线程
多线程:如果在main方法中创建了其他线程,则JVM就会在主线程和其他线程之间轮流切换,保证每个线程都有机会使用CPU资源,即使main方法执行完最后的语句,但JVM会等待所有线程结束后才结束程序
3、线程的状态与生命周期
线程状态:
新建状态: New 当Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建状态
运行状态:Runnable 当线程调用start()方法后并且JVM将CPU使用权切换至该线程时
中断状态: Timed_Waiting sleep(),wait()方法可将线程主动置于中断状态;当该线程无CPU使用权,或者执行出错时自动进入中断状态
死亡状态:Terminated run()执行或强制结束时
(二)线程的创建以及常用方法
线程的创建:
1、使用Thread子类
//创建线程方式一:继承Thread类,重写run()方法,调用start开启线程
public class Threadtest extends Thread {
//run方法线程体
@Override
public void run() {
for (int i1 = 0; i1 < 2000; i1++) {
System.out.println("===="+i1);
}
}
public static void main(String[] args) {
//main主线程
//创建一个线程对象
Threadtest threadtest = new Threadtest();
//调用start()方法开启线程
threadtest.start();
for (int i = 0; i < 2000; i++) {
System.out.println("+++" + i);
}
}
}
2、使用Thread类(实现Runnable接口)
//创建线程方式二:实现runnable接口,重写run方法,执行线程需要丢入runnable接口实现类
public class Threadtest implements Runnable{
//run方法线程体
@Override
public void run() {
for (int i1 = 0; i1 < 2000; i1++) {
System.out.println("===="+i1);
}
}
public static void main(String[] args) {
//创建runnable接口实现类对象
Threadtest threadtest = new Threadtest();
//创建一个线程对象,通过对象(代理)开启线程
new Thread(threadtest).start();
//等同于 new Thread(threadtest).start()
for (int i = 0; i < 2000; i++) {
System.out.println("+++" + i);
}
}
}
目标对象与线程的关系
1、完全解耦:在实现Runnable接口的类中不创建线程,在main方法中窜创建,这目标对象与线程不是组合关系,类中不包含对线程对象的引用。即创建目标对象的类不包含线程对象,在引用时重新创建线程对象。
2、弱耦合:目标对象可以组合线程,让线程做为自己的成员。即创建目标对象的类组合线程对象。
线程常用方法:
1、start():进入排队状态
2、run():使用CPU资源时执行该方法体
3、sleep():休眠
4、isAlive():是否死亡
5、currentThread():返回当前运行线程
6、interrupt():结束休眠
(三)线程的相关操作:同步、协调同步、联合
线程同步
1、线程同步机制:当一个线程A使用synchronized方法时,其他线程想使用这个synchronized方法就必须等待,直到线程A使用完该synchronized方法。
2、线程同步:当若干个线程都需要使用一个synchronzed修饰的方法时,多个线程调用该方法时必须遵守同步机制。
协调同步的线程
当出现某个线程占用该synchronized方法而不能结束时,应当做出一定协调
1、使用wait()方法将不能结束的线程进入中断状态,让出CPU使用权
2、在协调后,使用notify(一个线程继续),、或者notifyAll(所有线程,先中断先继续)让未执行的方法体从中断处继续执行
线程联合(插队)
在线程A执行时,联合B。则A立刻中断执行,一直等到它联合的线程B执行完毕,A再重新排队等待CPU资源,才恢复执行。
public class Threadtest implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(i + "号不要脸插队");
}
}
public static void main(String[] args) {
//线程启动
Thread thread = new Thread(new Threadtest());
thread.start();
//主线程
for (int i = 0; i < 100; i++) {
if(i==50){
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i + "号同学排队");
}
}
}
(四)守护线程
1、threadx.setDaemon(true);该方法将线程设置为守护线程,守护线程再所有用户线程执行结束时立刻结束运行,无论其代码是否执行完毕。
public class Threadtest {
public static void main(String[] args) {
Thread thread1 = new Thread(new LORD());
Thread thread2 = new Thread(new P());
thread1.setDaemon(true);//默认是false,表示为用户线程,true为守护线程
thread1.start();
thread2.start();
}
}
class LORD implements Runnable{
@Override
public void run() {
while(true) {
System.out.println("LORD在看着你");
}
}
}
class P implements Runnable{
@Override
public void run() {
for (int i = 0; i < 36500; i++) {
System.out.println("你不知道");
}
System.out.println("============你去看他了==========");
}
}
(五)Gui线程
当java程序包含GUI时,JVM会开辟更多线程,其中有两个线程比较重要AWT-EventQuecue和AWT-Windows,其分别处理事件和负责绘制窗口到桌面。
可以在事件中加入线程或者切换线程来达到程序目的。即在AWT-EventQuecue中启动其它线程或者使其它线程中断。
三、题库考查知识点整理
1、线程调用start()方法可以使一个线程成为可运行的,但是它不一定立即开始运行。
2、线程新建后,可以调用run方法进入排队状态。
3、run()方法是Runnable接口中的方法。
4、一个进程可以产生多线程。
5、wait()方法、notify()及notifyAll()方法在java.lang.Object中。
6、线程不调用start方法,JVM就不会把它当作一个线程来对待(JVM管理的线程队列有这个线程)。
7、线程处于“新建”状态时(在调用start方法之前),线程调用isAlive()方法返回的值是false。
8、一个线程A调用synchronized方法期间,其他线程不可以能成功调用这个synchronized方法。
9、一个线程A调用synchronized方法期间,执行sleep方法进入中断后,其他线程也不能成功调用这个synchronized方法。
10、新建状态的线程调用isAlive()方法返回的值是false。
11、currentThread()方法是Thread类中的static方法,该方法返回当前正在使用CPU资源的线程.
12、wait()、notify()和notifyAll()都是Object类中的final方法,被所有的类继承、且不允许重写的方法。
13、一个因执行wait方法进入中断状态的线程,需要其他线程执行notify()或notifyAll()通知它结束中断状态。
14、一个线程在执行同步方法时,如果执行wait()方法,使本线程进入中断,就允许其它线程使用这个同步方法。
15、javax.swing.Timer类称为计时器线程,计时器的监视器必须是组件类的子类的实例,否则计时器无法启动。
16、线程在执行完run()方法之前,如果再次让线程执行start方法,就会发生ILLegalThreadStateException 异常。
第十三章——Java网络编程
一、知识结构框架

二、知识点详解
URL类
描述:URL类用来封装一个具体资源的引用,可以通过其对象来获取URL中的资源,一个URL对象通常包含三个基本信息:协议、地址、资源。协议例如Http,地址为有效IP或域名,资源则是所获取的文件。
构造方法:URL(String protocol,String host,String file) throws MalformedURLException;
常用方法:openStream():可调用该方法,建立一个InputStream的对象,该输入流指向URL对象所包含的资源,通过该输入流可以将服务器上的资源信息读到客户端。
资源读取案例:类似爬虫
import java.io.InputStream;
import java.net.URL;
public class Urldemo {
public static void main(String[] args) {
try {
URL url = new URL("http://www.baidu.com");
InputStream in = url.openStream();
byte []b = new byte[1024];
int n = -1;
while ((n = in.read(b))!=-1){
String str = new String(b,0,n);
System.out.println(str);
}
}catch (Exception e){
System.out.println(e);
}
}
}
InetAddress类
**描述:**可以用InetAddress类获取域名或IP地址
方法:
//获取域名和IP地址
InetAddress address = InetAdderss.getByName("www.baidu.com");
//获取域名
InetAddress address = InetAdderss.getHostName("www.baidu.com");
//获取IP地址
InetAddress address = InetAdderss.getHostAddress("www.baidu.com");
套接字
描述:Socket称为套接字,要通过互联网进行通信,至少需要一对套接字,一个运行于客户机端,称之为ClientSocket,另一个运行于服务器端,称之为serverSocket。
根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认。

建立连接以后, 还需使用socket.getOutputStream()/getInputStream()方法建立DataInputStream,DataOutputStream对象,形成一个信息流通的通道。 再out.writeUTF(“xxx”)方法向流传出信息,通过String s = in.readUTF()方法写入传入的信息。
服务器
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class Server {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket =null;
DataInputStream in = null;
DataOutputStream out = null;
boolean flag = true;
try {
//建立与客户端的连接
serverSocket = new ServerSocket(6666);
socket = serverSocket.accept();//服务器监听消息
//建立输入流与输出流
out = new DataOutputStream(socket.getOutputStream());
in = new DataInputStream(socket.getInputStream());
//处理信息
while (flag){
String s = in.readUTF();
System.out.println("服务器收到的回复" + s);
Scanner scanner = new Scanner(System.in);
if (scanner.next() == "bye"){
flag = false;
}
out.writeUTF(scanner.next());
}
}catch (Exception e){
System.out.println("客户端已经断开");
}
}
}
客户端
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) {
Socket socket;
DataInputStream in = null;
DataOutputStream out = null;
boolean flag = true;
try{
//创建Socket连接
socket = new Socket("127.0.0.1",6666);
//建立输入流与输出流
in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
//处理信息
while (flag){
Scanner scanner = new Scanner(System.in);
if(scanner.next() == "bye"){
flag = false;
}
out.writeUTF(scanner.next());
String s = in.readUTF();
System.out.println("客户端收到的回复:" + s);
}
}catch (Exception e){
System.out.println("客户端已经断开");
}
}
}
UDP数据报
描述:基于UDP的通信基本模式为:将数据打包,称为数据包,将数据包发送到目的地;接收数据包,查看其内容。
与TCP协议不同的是,基于UDP的信息传递更快,但是用户无法知道数据是否正确到达,或者接收的顺序是否可靠,即UDP不及TCP可靠,但是比其快。
流程:每一个数据包的发送与接收,只需要发送端的数据包(DatagramPacket)的端口号与接受端(DatagramSocket)地址相同
在发送方:
需要设置DatagramPacket()创建一个对象称为数据包,该对象负责打包和写邮编(发送的目标端口号)
DatagramPacket(byte data[],int length,InetAddtress address,int port)
然后再使用DatagramSocket()创建一个对象,该对象负责发送数据包,可以为该对象设置端口号也可以不设置
该类的对象使用socket,调用send(packet)方法,进行数据包的发送
在接收方:
使用DatagramSocket()创建一个对象,该对象负责接收数据包,因为要收到已经设立好目标端口号的数据包,所以该处设立的端口号要与数据包的端口号一致
DatagramPacket packet = new DatagramPacket(container, 0, container.length);创建该类的对象,用于接收数据包再使用socket对象调用receive(packet),来接收数据包
发送线程
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
public class TalkSend implements Runnable {
DatagramSocket socket = null;
BufferedReader reader = null;
InputStreamReader in = null;
private int fromPort;
private String toIP;
private int toPort;
public TalkSend(int fromPort, String toIP, int toPort) {
this.fromPort = fromPort;
this.toIP = toIP;
this.toPort = toPort;
try {
//建立发送端口号,用于识别不用于发送
socket = new DatagramSocket(fromPort);
//设立输入流
in = new InputStreamReader(System.in);
reader = new BufferedReader(in);
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
//数据准备
while (true) {
String data = null;
try {
data = reader.readLine();
} catch (IOException e) {
e.printStackTrace();
}
byte[] bytes = data.getBytes();
//数据打包,并设置发送端口地址,此处与设立接收方的地址相同
DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length, new InetSocketAddress(this.toIP,toPort));
//发送数据包
try {
socket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
接收线程
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class TalkReceive implements Runnable{
DatagramSocket socket = null;
private int port;
private String msgFrom;
public TalkReceive(int port,String msgFrom) {
this.port = port;
this.msgFrom = msgFrom;
try {
//设立接收数据包的地址
socket = new DatagramSocket(port);
}catch (SocketException e){
e.printStackTrace();
}
}
@Override
public void run() {
try {
while (true) {
//准备接收数据包
byte[] container = new byte[1024];
DatagramPacket packet = new DatagramPacket(container, 0, container.length);
//接收数据包
socket.receive(packet);
byte[] data = packet.getData();
String datas = new String(data, 0, data.length);
System.out.println(msgFrom + ":" +datas);
if (datas.equals("bye")) {
break;
}
}
}catch (Exception e){
e.printStackTrace();
}
socket.close();
}
}
学生端
public class Student {
public static void main(String[] args) {
new Thread(new TalkSend(7777,"localhost",9999)).start();
new Thread(new TalkReceive(8888,"老师")).start();
}
}
老师端
public class Techer {
public static void main(String[] args) {
new Thread(new TalkSend(5555,"localhost",8888)).start();
new Thread(new TalkReceive(9999,"学生")).start();
}
}
三、题库考查知识点整理
1、java.net包中的URL类的实例,即对象封装着着一个具体的资源。
2、URL类创建对象需要捕获MalformedURLException异常 。
3、URL是Uniform Resource Locator的缩写。
4、一个URL对象通常包含最基本的三部分信息:协议、地址、资源。
5、URL类创建对象需要捕获MalformedURLException异常 。
6、URL对象调用InputStream openStream() 方法可以返回一个输入流,该输入流指向URL对象所包含的资源。
7、端口号是一个16位的0~65535之间的整数。
8、
Socket的构造方法Socket()创建一个未连接的套接字。
套接字再调用
public void connect(SocketAddress endpoint) throws IOException
请求和参数SocketAddress指定的服务器端的套接字建立连接。
9、客户端的程序使用Socket类建立负责连接到服务器的套接字对象。
10、客户端的程序使用Socket类建立负责连接到服务器的套接字对象。
11、服务器使用ServerSocket对象将客户端的套接字对象和服务器端的一个套接字对象连接起来,从而达到连接的目的。
12、服务器端的ServerSocket对象调用方法accept()返回一个和客户的套接字相连接的套接字对象。
第十四章——图形、图像与音频
一、知识结构框架

二、知识点详解
图形
1、程序框架

三、题库考查知识点整理
1、Line2D.Double:负责创建“直线”对象
2、RoundRectangle2D.Double:负责创建“圆角矩形”对象
3、Rectangle2D.Double:负责创建“矩形”对象
4、RoundRectangle2D.Double:负责创建“椭圆”对象
5、Arc2D.Double:负责创建“圆弧”对象
6、public void paint(Graphics g)方法是java.awt.Component类提供的方法。
7、Graphicd2D是Graphics的一个子类。
8、Line2D是java.awt.geom包中的类。
9、java.awt.geom包中的的Rectangle2D的静态内部类Double可以创建Rectangle2D对象。
10、new Rectangle2D.Double(0,0,100,50)创建了一个左上角坐标是(0,0),宽和高分别是100和50的Rectangle2D矩形对象。
11、AudioClip和Applet类属于java.applet包中的类。
12、Graphics2D对象调用drawString(String s, int x, int y)方法从参数x、y指定的坐标位置处,从左向右绘制参数s指定的字符串s。
13、new Ellipse2D.Double (10,5,100,50 )创建了一个左上角坐标是(10,5),宽和高分别是100和50的Ellipse2D椭圆对象。
第十五章——Java泛型与集合框架
一、知识结构框架

二、知识点详解
###1、泛型
编写的代码可以被不同类型的对象所重用,主要目的是可以建立具有类型安全的集合框架。
1.1 泛型类
具有泛型变量的类,在类名后用代表引用类型,如ArrayList,HashMap,HashSet
//ArrayList部分源码
public class ArrayList<E> extends AbstractList<E>
implements List<E>,RandomAccess,Cloneable,java.io.Serializable{
public E get(int index){}
}
1.1.1 设计泛型类
public class Interval<T>{
private T lower;
public getLower(){
return lower;
}}
1.1.2 调用泛型类
Interval<Integer> v = new Interval<Integer>();Interval<Integer> v = new Interval<>();//后面的可以省略
1.2 泛型方法
具有泛型参数的方法,可以在普通类或泛型类中,定义的泛型在修饰符后,返回类型前
1.2.1 设计泛型方法
public class ArrayUtil{ public static<T> T getMiddle(T... a){ return a; }
1.2.1 调用泛型方法
ArrayUtil arr = new ArrayUtil();String s = a.<String>getMiddle("a","b","c")
1.3 泛型接口
与泛型类相似,在类名后加,实现接口时,指定类型
1.3.1 设计泛型接口
public interface Calculator<T>{ public T add(T operand1,Toperand2);}
1.3.2 实现泛型接口
public class IntegerCalculator implements Calculator<Integer>{
public Integer add(Integer operand1,Integer Toperand2){
return operand1 + operand2;
}
IntegerCalculator a = new IntegerCalculator();
Calulator<Integer> c = new IntegerCalculator();//用泛型接口声明对象时
2、集合框架
框架集合


2.1 List
2.1.1 ArrayList实现了长度可变的数组
对象创建:List list = new ArrayList();
方法:与List方法相同

使用例子:
public class Demo {
public static void main(String[] args) {
//1、创建4个学生对象
Student stu1 = new Student("Tom", 10);
Student stu2 = new Student("Aimee", 11);
Student stu3 = new Student("George", 11);
Student stu4 = new Student("Angelia", 13);
//2、创建ArrayList集合对象并把4个学生放入其中
List list = new ArrayList();
list.add(stu1);
list.add(stu2);
list.add(stu3);
list.add(2,stu4);//添加stu4到指定的位置
//3、输出集合中学生的总数
System.out.println("总共有学生"+list.size()+"个。");
//4、通过遍历集合显示所有学生的信息
for (int i = 0; i < list.size(); i++) {
Student student=(Student)list.get(i);
System.out.println(student.getName()+"\t"+student.getAge());
}
}
}
2.1.2LinkedList采用链表存储方式
对象创建:LinkedList mylist = new LinkedList();
方法:在List方法上新增

例子:
//对象创建
LinkedList<String> mylist = new LinkedList<String>();
//常用操作
mylist.add("h");
mylist.add("o");
mylist.add("w");
mylist.remove(1);
mylist.get(1);
mylist.getFirst();
mylist.getLAst();
mylist.removeFirst();
mylist.removeLAst();
int n = mylist.size();
int index = mylist.indexOf("o");
int index = mylist.lastindexOf("o");
//遍历
Iterator<String> iter = mylist.iterator;
while(iter.hasNext()){
System.out.println(iter.next);
}
2.2 Map
对象创建:Map countries = new HashMap();

使用例子:
public class Test4 {
public static void main(String[] args) {
Map countries = new HashMap();
countries.put("CN", "中华人民共和国");
countries.put("RU", "俄罗斯联邦");
countries.put("FR", "法兰西共和国");
countries.put("US", "美利坚合众国");
String country = (String) countries.get("CN");
System.out.println("CN对应的国家是:" + country);
System.out.println("Map中共有"+countries.size()+"组数据");
countries.remove("FR");
System.out.println("Map中包含FR的key吗?" +
countries.containsKey("FR"));
System.out.println( countries.keySet() ) ;
System.out.println( countries.values() );
System.out.println( countries );
}
}
三、题库考查知识点整理
1、LinkedList、Stack、ArrayList实现了List接口。
2、removeLast()是LinkedList有,但ArrayList类没有的方法。
3、ArrayList的public void add(int index,E element)方法的执行效率低于LinkedList的效率。
4、ArrayList的public E get(int index)方法的执行效率效率高于LinkedList的效率。
5、ArrayList的public E remove(int index)方法的执行效率低于LinkedList的效率。
6、ArrayList的public E get(int index)方法的执行效率效率高于LinkedList的效率。
7、LinkedList类不是线程安全的,即提供的添加,删除操作都不是同步(synchronized)的。
8、LinkedList类不是线程安全的,即提供的添加,删除操作都不是同步(synchronized)的。
9、Vector类是线程安全的,即提供的添加,删除操作都是同步(synchronized)的。
10、Stack类是线程安全的,即提供的压栈,弹栈操作都是同步(synchronized)的。
11、HashMap<K,V>对象不是采用顺序表这种数据结构存储数据的。HashMap<K,V>对象采用散列表这种数据结构存储数据。