Java 高级部分学习
第八章:多线程
8.1 基本概念
-
程序
是为完成特定任务,用某种语言编写的一组指令的集合。即指一段静态的代码,静态对象
-
进程
是程序的一次执行过程,或者是正在运行的一个程序。是一个动态的过程:有他自身的产生、存在和消亡 —声明周期
进程作为资源的分配的单位,系统在运行时会 为每个进程分配不同的内存区域
-
线程(Thread)
进程可进一步细化为线程 ,是一个程序内部的一条执行路径。
若一个进程同一时间并行执行多个线程,就是支持多线程的
线程作为调度和执行的单位,每个线程都拥有独立的运行栈和程序计数器(pc),线程切换的开销小
一个进程中的多个线程共享相同的内存单元/内存地址空间 -> 他们从同意堆中分配对象,可以访问相同的变量和对象。这就使得线程间通信更简便、高效。单多个线程操作共享的系统资源可能就会带来安全隐患。
- 并行与并发
- 并行:多个CPU同时执行多个任务。比如:多个人同时做不同的事。
- 并发:一个CPU(采用时间片)同时执行多个任务。比如:多个人同时做一个任务
- 使用多线程的优点
- 提高应用程序的响应。堆图形画界面更有意义,可增强用户体验。
- 提高计算机系统CPU的利用率
- 改善程序结构。将长又复杂的进程分成多个线程,独立运行,利于理解和修改
- 何时需要多线程
- 程序需要同时执行两个或者多个任务
- 程序需要实现一些需要等待的任务时,入用户输入、文件读写操作、网络操作、搜索等
- 需要一些后台运行的程序时。
- 并行与并发
8.2 线程的创建和使用
-
多线程的创建,方式一:继承于Thread
- 创建一个继承与Thread 类的子类
- 重写Thread 类的run() -->针对方法体,将此线程执行的操作声明在run()中
- 创建Thread 类的子类的对象
- 通过此类对象调用start()
class MyThread extends Thread(){
public void run(){
//操作 输出100以内的偶数
for(int i=0;i<=100;i++){
if(i%2==0){
System.out.println(i);
}
}
}
}
public class ThreadTest{
public static void main(String[] args){
//创建子类对象
MyThread t1 = new MyThread();//快捷键创建对象 alt+enter
//通过对象调用start():① 启动当前线程 ②调用当前线程的run()
t1.start();
//问题1 :我们不能通过调用run()的方式启动线程,用start()
// t1. run(();
//如下操作仍旧时在main()中打开的
//问题2:在启动一个线程,不能用start()的线程去执行,会发生报错
//应该重新啊创建一个线程的对象,让他去s'ta
System.out.println("hello");
}
}
2. Thread 类的有关方法
1. start():启动当前线程;调用当前线程的run() 方法
2. run (): 通常需要重写Thread类中的此方法,将创建的线程要执行的操作声明在此方法中
3. currentThread():静态方法,返回当前代码执行的线程
4. getName( ) : 获取当前线程的名字
5. setName():设置当前线程的名字
6. yield ( ) : 释放当前CPU的执行权。存在又一次分配给这个进程
7. join():在线程A中调用线程B的join()方法,此时线程A就进入阻塞状态,直到线程B 完全执行以后,线程A才开始执行
8. stop() : 已经过时。当执行此类方法时,直接结束
9. sleep(long millitime //毫秒): 让当前线程“睡眠”指定的“millitime”毫秒之间内,当前线程时阻塞状态。
10. isAlive():判断当前线程是否还存活。
-
线程的调度
-
线程的优先级
- NORM_PRIORITY : 5 -->默认的优先级
-
如何获取和设置当前线程的优先级
-
getPriority():获取当前线程优先级
-
setPriority(int newPriority):改变线程的优先级
说明:高优先级的线程要抢占低优先级线程CPU的执行权。但是只是从概率上来讲,高优先级的线程高概率的情况下被执行。并不意味着只有当高优先级的线程执行完以后,低优先级的线程才执行。
-
-
-
多线程的创建,方式二:实现Runnable接口
1. 创建一个实现了Runnable接口的类 2. 实现类去实现Runnable中的抽象方法:run() 3. 创建实现类的对象 4. 将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象 5. 通过Thread 类的对象调用start()
class MThread implements Runnable{ //1.创建了一个实现了Runnable接口的类 public void run(){//2.实现Runnable中的抽象方法 for(int i=0;i<=100;i++){ if(i%==0){ System.out.println(i); } } } } public class ThreadTest1{ public static void main(String[] args){ //3.创建实现类的对象 MThread mThread =new MThread(); //4.将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象 Thread t1 = new Thread(mThread); //5.通过Thread类的对象调用start()②调用当前线程的run()方法--> 调用了Runnable类型的target的run() t1.start(); //在启动一个线程,遍历100以内的偶数 Thread t2 = new Thread(mThread);//共用同一个mTread t2.start(); } }
-
比较线程的两种方式
开发中:优先选择,实现Runnable接口的方式
原因:
1.实现的方式没有类的单继承性的局限性
2. 实现的方式更适合来处理多个线程有共享数据的情况
联系:public class Thread implements Runnable
相同点:两种方式都需要重写run(),将线程要执行的逻辑声明在run()中。
427
8.3线程的声明周期
第九章:Java常用类
第十章:枚举类&注解
第11章:Java集合
第12章:泛型
第13章:IO流
在初学Java时,IO流是我遇到的一个很头疼的东西,Java IO 体系看起来类很多,感觉很复杂,但其实是 IO 涉及的因素太多了。在设计 IO 相关的类时,编写者也不是从同一个方面考虑的,所以会给人一种很乱的感觉,并且还有设计模式的使用,更加难以使用这些 IO 类,所以特地对 Java 的 IO 做一个总结。
1.IO流总览
话不多说,直接上图:
2.IO流分类
按照“流”的数据流向,可以将其化分为:输入流和输出流。
按照“流”中处理数据的单位,可以将其区分为:字节流和字符流。在java中,字节是占1个Byte,即8位;而字符是占2个Byte,即16位。而且,需要注意的是,java的字节是有符号类型,而字符是无符号类型!
字节流的抽象基类:
InputStream,OutputStream
字符流的抽象基类:
Reader,Writer
由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀,如InputStream的子类FileInputStream,Reader的子类FileReader。
1.字符流
1.Writer:字符输出流
Writer是字符输出流的基类,Writer的主要方法如下:
Writer append( char c) 将指定的字符附加到此作者
Writer append(CharSequence csq) 将指定的字符序列附加到此作者
Writer append(CharSequence csq, int start, int end) 将指定字符序列的子序列附加到此作者
abstract void close() 关闭流,先刷新
abstract void flush() 刷新流
void write( char [] cbuf) 写入一个字符数组。
abstract void write( char [] cbuf, int off, int len) 写入字符数组的一部分
void write( int c) 写一个字符
void write(String str) 写一个字符串
void write(String str, int off, int len) 写一个字符串的一部分
我们知道IO流主要是用于操作文件的,但是从上图中我们发现Writer的直接子类中好像并没有直接操作文件,但是细心的你注意到,在Writer的子类OutputStreamWriter的子类中有一个类叫做FileWriter,File这个单词我们很熟悉——文件,大家可以推测一下这个类是可以用于操作文件的,下面我们来学习一下FileWriter的用法
第14章:网络编程
1、网络协议
TCP三次握手过程:
TCP四次挥手过程:
TCP与UDP的区别
TCP基于连接,UDP是无连接的;
对系统资源的要求,TCP较多,UDP较少;
UDP程序结构较简单;
TCP是流模式,而UDP是数据报模式;
TCP保证数据正确性,而UDP可能丢包;TCP保证数据顺序,而UDP不保证;
2、Socket整体流程
第15章:反射
1、反射机制的功能
Java反射机制主要提供了以下功能:
在运行时判断任意一个对象所属的类。
在运行时构造任意一个类的对象。
在运行时判断任意一个类所具有的成员变量和方法。
在运行时调用任意一个对象的方法。
生成动态代理。
2、 实现反射机制的类
Java中主要由以下的类来实现Java反射机制(这些类都位于java.lang.reflect包中):
Class类:代表一个类。 Field类:代表类的成员变量(成员变量也称为类的属性)。
有三种方式可以获得类的Class对象实例:
1、Object的getClass()方法
// 创建对象,通过对象的getClass()方法获取Class对象实例
Class clazz = new HelloWorld().getClass();
2、类型的.class
// 通过类型的class获得Class实例
Class clazz = HelloWorld.class;
3、Class.forName(“类的完全限定名”)
// 通过Class.forName("类的完全限定名")获取Class对象实例
try {
Class clazz = Class.forName("com.learn.demo.reflection.HelloWorld");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Method类:代表类的方法。
// 获得类的public成员方法
Method[] methods0 = clazz.getMethods();
Constructor类:代表类的构造方法。
// 构造方法-一个int类型参数的构造方法
Constructor constructor0 = clazz.getConstructor(int.class);
Object obj0 = constructor0.newInstance(1);
// 构造方法-一个int类型参数和一个String类型参数的构造方法
Constructor constructor1 = clazz.getConstructor(int.class, String.class);
Object obj1 = constructor1.newInstance(2, "我出生了!")
获得类的成员变量
// 通过getDeclaredFields方法获取private成员变量
Field [] fields = clazz.getDeclaredFields();
Array类:提供了动态创建数组,以及访问数组的元素的静态方法。
//利用Array.newInstance创建一维数组
int rows = 3;
int cols = 2;
Integer[] array = (Integer[]) Array.newInstance(Integer.class,rows);
Array.set(array,0,110);
//利用Array.newInstance创建多维数组
Double[][] arraymn = (Double[][]) Array.newInstance(Double.class,rows,cols);
Array.set(arraymn[0],0,1D);