欢迎光临散文网 会员登陆 & 注册

基于《java2实用教程》的java知识点复习整理【第十二章——第十五章】

2023-05-24 11:11 作者:欢喜y1  | 我要投稿

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>对象采用散列表这种数据结构存储数据。


    基于《java2实用教程》的java知识点复习整理【第十二章——第十五章】的评论 (共 条)

    分享到微博请遵守国家法律