概念:存储多个相同数据类型的数据结构
特点:长度固定
声明和初始化:数据类型[] 变量名 = 初始化(动态初始化、静态初始化)
索引:从0开始
算法:
(1)排序算法
(2)查找算法
多维数组:Java允许数组的元素又是一个数组
File类:Java中操作文件或目录的类。
常用的方法:创建、删除、重命名、获取
流:Stream 数据通信的通道。
分类
(1)根据功能分:
①Java中的节点流:文件流(操作文件的数据都是跟文件有关)如:FileXXX;内存流(操作的数据都是跟数组有关)如ByteXXX
②Java中的过滤流:缓冲流、对象六、数据流、转换流等等
(2)根据单位分:字节流、输出流
(3)根据方向分:输入流、输出流
输入流:read、skip(跳过)
输出流:write、flush(刷新)
异常分类:
(1)错误(Error):人为不可解决
(2)异常(Exception):
①运行时异常(RuntimeException):代码在运行阶段,显示的异常。如IndexOutBoundException
②编译时异常:代码在编译阶段,显示的异常。如IOException
反射机制是Java程序在运行中,动态获取类的信息(方法、属性、注解等),并且还可以调用类的属性和方法。这种动态获取类的信息、以及动态调用对象的方法和属性的行为就i叫反射。
反射就是可以获取类的信息和执行对应的方法。
运行时获取类中的属性
运行时获取类中的方法
运行时创建类的对象
运行时执行类中的方法
运行时校验属性是否属于某个类
实现动态代理
通过反射实现类中的属性、方法的获取,还可以运行类中的方法。
创建Class对象的三种方式
(1)类名.class
(2)Class.forName
(3)对象名.getClass
代码演示:获取类中的属性
public static void main(String[] args) {
//1.创建反射对象--Class
Class<Student> clz=Student.class;
//2.获取Student类中的属性
//公共属性,包含继承属性
Field[] arrF=clz.getFields();
//所有属性,不包含继承的属性
Field[] arrF2=clz.getDeclaredFields();
//3.显示 获取到的属性
System.err.println("公共属性,包含继承属性:"+Arrays.toString(arrF));
System.err.println("所有属性,不包含继承的属性:"+Arrays.toString(arrF2));
}
代码演示:获取类中的方法
public static void main(String[] args) {
//1.获取反射对象
Class<Student> clz=Student.class;
//2.获取对象中的方法
//公共方法,包含继承方法
Method[] arrM=clz.getMethods();
//所有方法,不包含继承方法
Method[] arrM2=clz.getDeclaredMethods();
//3.显示对应的方法
System.err.println("公共方法:"+Arrays.toString(arrM));
System.err.println("所有方法:"+Arrays.toString(arrM2));
}
代码演示:通过反射执行类中的方法
public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//1.获取反射对象
Class<Student> clz=Student.class;
//执行公共方法
//2.获取要运行的方法对象
Method m=clz.getDeclaredMethod("eat");
//3.创建对应的对象
Student s=clz.newInstance();
//4.执行方法
/*
* invoke 参数说明:
* 1.方法对应的对象
* 2.方法需要的参数,可变参数*/
m.invoke(s);
//执行私有方法
Method rm=clz.getDeclaredMethod("run");
//设置 是否过滤访问校验 私有方法或属性,必须设置过滤访问校验
rm.setAccessible(true);
rm.invoke(s);
}
概念:软件在运行时的一种状态,会占用CPU、内存等资源。即可理解为正在运行的程序。
特点:独立性、动态性、并发性
概念:代码的执行路径,是进程的一部分。一个进程可以有多个线程,每个线程都可以执行自己的内容或者多个线程共同执行一个任务。也就是说有了多线程,就可以同时干多件事情
线程是CPU的最小调度单位
CPU可以很快的在多个线程间切换
运行时的线程,随时都可以被CPU挂起
线程的抢占发生在任意时期
一个程序可以有多个进程
一个进程可以有多个线程,但是必须要有个主线程
进程间不能共享资源,但是线程之间可以共享资源
Java中的main方法其实就是主线程,main内部的代码执行都是主线程在执行
我们手动创建的方法都叫子线程
public static void main(String[] args) {
//1.创建线程接口的对象 匿名内部类-实例化 接口、抽象类
Runnable rb=new Runnable() {
@Override
public void run() {
System.err.println("我是子线程-"+
Thread.currentThread().getName());
}
};
//2.创建线程对象,并定义线程要做的事情
Thread td=new Thread(rb);
//3.启动线程
//td.start();//才是子线程在运行
td.run();//这样的话,代码的运行就是主线程运行。
System.err.println("主线程-"+Thread.currentThread().getName());
}
Java中的线程类:Thread
Java中的线程都需要接口,线程接口:Runnable。
这个接口里只有一个方法:run
每次在写子线程时,都需要在run方法内部实现自己要做的事
启动线程用的是start方法
线程常用的的三种创建方式
(1)实现Runnable接口
(2)自定义类实现Thread类的子类,重写run方法
(3)实现Callable接口(JDK1.8新特性)
采用匿名内部类,直接完成接口的实例化,并重写run方法
自定义实现接口
package com.qfedu.b_thread;
/**
* 实现Runnable接口
*/
public class MyRunnable implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 100; i++) {
System.out.println("子线程-数羊" + i);
}
}
}
在这里插入代码片
```java
package com.qfedu.b_thread;
/**
* main方法测试
*/
public class CreateThread01 {
public static void main(String[] args) {
// 1. 创建接口的实现类
MyRunnable mr = new MyRunnable();
// 2. 创建线程对象
Thread td = new Thread(mr);
// 3. 启动线程
td.start();
}
}
敲黑板:实际上我们可以通过匿名内部类来实现Runnable接口
创建类继承Thread,并重写run方法
public class HelloThread extends Thread{
@Override
public void run() {
System.err.println(" 继承线程类 实现子线程");
}
}
public static void main(String[] args) {
//1.实例化自定义线程类对象
HelloThread ht=new HelloThread();
//2.启动线程
ht.start();
}
说明:Callable接口是JDK1.8新版本推出的线程创建方式,线程可以带返回值
操作步骤:
(1)实现Callable接口,并指定线程的返回值类型
(2)创建FutureTask对象
(3)创建线程对象,并传递任务对象
(4)启动线程
(5)获取线程的返回值
public class MyCallable implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.err.println("子线程,带返回值的");
return new Random().nextInt(10);
}
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
//1.创建 Callable接口的实现类对象
MyCallable mc=new MyCallable();
//2.创建任务对象
FutureTask<Integer> ft=new FutureTask<Integer>(mc);
//3.创新线程对象
Thread td=new Thread(ft);
//4.启动线程
td.start();
//5.获取线程的返回值 只有在线程执行结束之后才会返回
System.err.println("返回值:"+ft.get());
}
继承Thread类
编写简单,但由于Java的单继承特性,所以这种类无法在继承其他类,无法实现多个线程的资源共享
实现Runnable接口
编写稍微复杂一点,接口可以多实现,还可以实现多个线程的资源共享,推荐使用。
实现Callable接口
编码较为复杂,但是线程执行完之后有返回值
小结:开发中,创建线程时,如果要求线程存在返回值,使用Callable;不需要线程返回值时,使用Runnable接口的实现
线程有五大状态,分别是:新建、就绪、运行、阻塞、销毁
新建:当我们实例化线程对象的时候,就是新建
就绪:当我们调用现成的start方法之后,线程就会进入就绪状态
运行:线程获取CPU的调度之后,线程抢到时间片,可以用来运行自己的任务
阻塞:线程因为资源竞争,或主动方法调用,让线程进入阻塞状态。比如sleep()、wait()、join()、synchronized()
销毁:当线程的run方法执行结束之后,就会进入到销毁状态
敲黑板:程序的结束是指内部的线程全部进入到销毁状态
线程分为:用户线程和守护线程
Java中默认的线程是用户线程
代码演示
public static void main(String[] args) {
// 代码演示线程的类型 用户线程和守护线程
//默认的就是用户线程
Thread th=new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
System.err.println("子线程");
}
});
th.start();
//创建守护线程
Thread th2=new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
System.err.println("子线程--守护线程");
}
});
//设置当前的线程对象是否为守护线程,默认为false
th2.setDaemon(true);
//启动线程
th2.start();
}
主线程和GC线程就是经典的用户和守护线程案例
守护线程的特点:当守护的用户线程销毁的时候,守护线程也会跟着销毁。无论守护线程是否执行结束都会随着用户线程一起销毁。
守护线程又叫后台线程。
当用户线程销毁的时候,会将自己未执行结束的守护线程一起销毁
public class LogRunable implements Runnable{
@Override
public void run() {
//死循环
while(true) {
//间隔3秒 打印日志……
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("守护线程:记录日志中……");
}
}
}
public static void main(String[] args) {
//演示 用户线程和守护线程
//创建用户线程
Thread td=new Thread(new Runnable() {
@Override
public void run() {
//拥有守护线程
Thread t=new Thread(new LogRunable());
//设置为守护线程 守护的是当前的用户线程
t.setDaemon(true);
t.start();
for(int i=1;i<10001;i++) {
if(i%33==0&& i%77==0) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.err.println("用户线程--"+i);
}
}
}
});
//启动用户线程
td.start();
}
线程的优先级就是线程获取CPU的概率,优先级别越高,获得CPU的概率越大
从小到大,1~10之间,10是优先级最高,默认的优先级是5
通过线程的setPriority设置线程的优先级
通过线程的getPriority获取线程的优先级
设置优先级需要在start之前
线程的优先级默认是5
小磊同学,看电视的同时可以玩游戏、还可以说话聊天。用多线程来描述。
代码演示:
public static void main(String[] args) {
//三个线程-分别做不同的事情
//匿名内部类 实现
Thread td1=new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
System.err.println("小磊在看电视--->爱情电视剧 泡沫剧");
}
});
td1.start();
Thread td2=new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
System.err.println("小磊在玩游戏--->斗地主、俄罗斯方块、扫雷");
}
});
td2.start();
Thread td3=new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
System.err.println("小磊在聊天--->单身男士喜欢的内容");
}
});
td3.start();
}
Lambda是JDK8之后支持的一种简写模式,可以快速实现接口实例化
语法格式:(参数) -> {方法重写}
规则:
(1)接口
(2)接口中只能有一个抽象方法
(3)Lambda表达式的结果是一个对象
代码演示
public interface IEat {
void eat();
}
public static void main(String[] args) {
//1.基于Lambda表达式完成接口的实例化
IEat ie=()->System.err.println("吃啥呢?");
ie.eat();
}