今日内容
- 算法----------------->理解原理,做好笔记
- 冒泡排序
- 选择排序
- 二分查找
- 异常
- 异常的概述
- 异常的产生
- 异常的处理-------------------->掌握
- 自定义异常
- 创建并启动线程的三种方式-------------------->掌握
第一章 冒泡排序
1.1 冒泡排序
-
冒泡排序概述
- 对要进行排序的数据中相邻的数据进行两两比较,将较大的数据放在后面
- 每一轮比较完毕,最大值在最后面,下一轮比较就少一个数据参与
- 每轮比较都从第一个元素(索引为0的元素)开始
- 依次执行,直至所有数据按要求完成排序
- 如果有n个数据进行排序,总共需要比较n - 1轮
-
冒泡排序图解
-
冒泡排序代码实现
/** * Created by PengZhiLin on 2021/8/6 9:17 */ public class Test { public static void main(String[] args) { int[] arr = {45, 25, 35, 55, 15}; // 冒泡排序 // 外层循环控制比较的轮数 for (int i = 0; i < arr.length - 1; i++) { // 内层循环控制每轮比较的次数 for (int j = 0; j < arr.length - 1 - i; j++) { // 比较并交换 if (arr[j] > arr[j+1]){ int temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } System.out.println("排序后的数组:"+ Arrays.toString(arr)); } }
第二章 选择排序
2.1 选择排序
-
选择排序概述
- 对要进行排序的数组中,选中某个位置元素(从头依次选中)依次和后面的元素逐个比较,将较大的数据放在后面
- 每一轮比较完毕,最小值在最前面,下一轮比较就少一个数据参与
- 每轮比较都从下一个(轮数+1)元素开始
- 依次执行,直至所有数据按要求完成排序
- 如果有n个数据进行排序,总共需要比较n - 1轮
-
选择排序图解
-
选择排序代码实现
/** * Created by PengZhiLin on 2021/8/6 9:50 */ public class Test { public static void main(String[] args) { int[] arr = {45, 25, 35, 55, 15}; // 选择排序 // 外层循环控制比较的轮数 for (int i = 0; i < arr.length - 1; i++) { // 内层循环控制每轮比较的次数 for (int j = i + 1; j < arr.length; j++) { // 比较并交换 if (arr[i] > arr[j]) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } } System.out.println("排序后的数组:" + Arrays.toString(arr)); } }
第三章 二分查找
3.1 二分查找
-
二分查找
- 每一次都去获取数组的中间索引所对应的元素,然后和要查找的元素进行比对,如果相同就返回索引
- 如果不相同,就比较中间元素和要查找的元素的值:
- 如果中间元素的值大于要查找的元素,说明要查找的元素在左侧,那么就从左侧按照上述思想继续查询(忽略右侧数据);
- 如果中间元素的值小于要查找的元素,说明要查找的元素在右侧,那么就从右侧按照上述思想继续查询(忽略左侧数据);
-
前提:数据有序
-
二分查找图解
-
二分查找代码实现
package com.itheima.demo3_二分查找; /** * Created by PengZhiLin on 2021/8/6 10:04 */ public class Test { public static void main(String[] args) { int[] arr = {10, 14, 21, 38, 45, 47, 53, 81, 87, 99}; System.out.println(searchElement(arr, 53));// 6 System.out.println(searchElement(arr, 50));// -1 } // 定义一个方法,实现二分查找 public static int searchElement(int[] arr, int num) { // 1.定义一个left变量,记录最左边元素的索引,初始值为0 int left = 0; // 2.定义一个right变量,记录最右边元素的索引,初始值为数组长度-1 int right = arr.length - 1; // 3.使用while循环查找,查找条件:left<=right while (left <= right) { // 4.在循环中,计算中间索引 int middle = (left + right) / 2; // 5.判断中间索引对应的元素与要查找的元素是否相等 if (arr[middle] == num) { // 6.如果相等,就直接返回中间索引 return middle; }else if(arr[middle] > num) { // 6.如果中间索引对应的元素 大于 要查找的元素,说明要查找的元素在左边,忽略右侧数据 right = middle - 1; }else if(arr[middle] < num) { // 6.如果中间索引对应的元素 小于 要查找的元素,说明要查找的元素在右边,忽略左侧数据 left = middle + 1; } } // 来到这里,说明没有找到,返回-1作为标识 return -1; } }
第四章 异常
4.1 异常
异常概念
- 概述: 指的是java程序运行期间出现的不正常情况,导致jvm终止程序的运行
- 特点:
- java是面向对象的语言,产生的每个异常其实都是一个异常对象,每个异常对象一定会有所属的异常类
- 常见的异常类:
- ClassCastException
- NullPointerException
- ArrayIndexOutOfBoundsException
- ArithmeticException
- …
- java中默认将异常抛给jvm处理,而jvm处理的方式就是中断程序运行,将异常信息输出到控制台
异常体系
- Throwable类: 是 Java 语言中所有错误或异常类的父类
-
Error类(错误): 表示错误,不可以通过代码进行纠正使得程序继续运行,只能事先避免
- eg: 栈内存溢出错误… XXXError类
-
Exception类(异常):表示异常,可以通过代码进行纠正使得程序继续运行
- eg: ClassCastException,NullPointerException,ArrayIndexOutOfBoundsException,ArithmeticException
-
异常分类
- 编译异常: 程序在编译期间出现的异常,如果编译期间不处理,程序无法通过编译
- 除了RuntimeException及其子类都是表示编译异常
- 运行异常: 程序在运行期间出现的异常,如果不处理,程序可以通过编译,但在运行的时候会出现异常
- RuntimeException及其子类都是表示运行异常
异常的产生过程解析
先运行下面的程序,程序会产生一个数组索引越界异常ArrayIndexOfBoundsException。我们通过图解来解析下异常产生的过程。
工具类
public class ArrayTools {
// 对给定的数组通过给定的角标获取元素。
public static int getElement(int[] arr, int index) {
int element = arr[index];
return element;
}
}
测试类
public class ExceptionDemo {
public static void main(String[] args) {
int[] arr = { 34, 12, 67 };
int num = ArrayTools.getElement(arr, 4);
System.out.println("num=" + num);
System.out.println("over");
}
}
上述程序执行过程图解:
第五章 异常的产生和处理
5.1 异常的产生
throw关键字的作用
-
在java中,提供了一个throw关键字,它用来抛出一个指定的异常对象。
-
throw用在方法内,来抛出一个异常对象,将这个异常对象传递到调用者处,并结束当前方法的执行。
throw关键字的使用格式
-
格式:
throw 异常对象;
-
代码:
/** * Created by PengZhiLin on 2021/8/6 10:58 */ public class Test { public static void main(String[] args) { System.out.println("开始"); method1(10); System.out.println("结束"); } public static void method1(int num){ if (num == 10){ // 可能会产生异常---创建异常对象 // throw**用在方法内,来抛出一个异常对象**,将这个异常对象传递到调用者处,并**结束当前方法的执行**。 throw new ArithmeticException("数学运算异常"); }else{ System.out.println("num不等于10"); } } }
5.2 声明处理异常
-
概述:使用throws关键字将异常标识出来, 表示当前方法不处理异常,而是提醒给调用者, 让调用者来处理…
-
格式:
修饰符 返回值类型 方法名(形参列名) throws 异常类型1,异常类型2,...{}
-
特点:
-
throws关键字是用在方法的声明之上的,也就是方法小括号的后面
-
throws可以一次抛一个或多个异常
-
使用声明处理异常,处理完后,如果程序运行期间没有出现异常,程序可以继续往下执行
-
使用声明处理异常,处理完后,如果程序运行期间有出现异常,程序不可以继续往下执行
-
代码:
/** * Created by PengZhiLin on 2021/8/6 11:08 */ public class Test { // 表示当前main方法不处理该异常,而是提醒调用者(jvm)来处理 public static void main(String[] args) throws ParseException{ /* - 概述:使用**throws关键字**将异常标识出来, 表示当前方法不处理异常,而是提醒给调用者, 让调用者来处理.... - 格式: `修饰符 返回值类型 方法名(形参列名) throws 异常类型1,异常类型2,...{}` */ System.out.println("开始"); //**使用声明处理异常,处理完后,如果程序运行期间出现了异常,程序不可以继续往下执行** //method(10); //**使用声明处理异常,处理完后,如果程序运行期间没有出现异常,程序可以继续往下执行** method(20); System.out.println("结束"); } // 表示当前method方法不处理该异常,而是提醒调用者(main)来处理 public static void method(int num) throws ParseException{ if (num == 10){ // 产生一个异常 throw new ParseException("解析异常",num); }else{ System.out.println("num不等于10"); } } }
-
-
使用场景:
- 用来处理编译异常,并且该程序在运行期间不会出现异常
-
声明处理多个异常:
// 表示当前method2方法不处理该异常,而是提醒调用者(main)来处理 public static void method2(int num) throws ParseException,FileNotFoundException{ if (num == 10){ // 产生一个异常 throw new ParseException("解析异常",num); }else{ throw new FileNotFoundException("文件找不到异常"); } } // 表示当前method3方法不处理该异常,而是提醒调用者(main)来处理 public static void method3(int num) throws Exception{ if (num == 10){ // 产生一个异常 throw new ParseException("解析异常",num); }else{ throw new FileNotFoundException("文件找不到异常"); } }
5.3 捕获处理异常try…catch
-
概述: 也是一种处理异常的方式,这种处理异常的方式处理完异常后,无论程序是否发生异常,程序都可以继续往下执行.
-
格式:
try{ // 可能会发生异常的代码 }catch(异常类型 变量名){ // 打印异常的信息,发生异常后需要执行的代码 } // 继续往下执行
- 注意:
- try,catch都不能单独使用
- try中的代码如果发生了异常,try中发生异常位置之后的代码就不执行了
- 注意:
-
执行流程:
- 首先执行try中的代码:
- 如果try中的代码发生了异常,就会执行catch里面的代码,执行完catch里面的代码后,程序继续往下执行
- 如果try中的代码没有发生异常,就不会执行catch里面的代码,而是继续往下执行
-
代码:
/** * Created by PengZhiLin on 2021/8/6 11:22 */ public class Test { public static void main(String[] args) { // 运行异常 System.out.println("开始"); try{ System.out.println("try中发生异常前的代码"); System.out.println(1/0); //System.out.println(1/1); System.out.println("try中发生异常后的代码"); }catch (ArithmeticException e){ System.out.println("发生了异常"); } System.out.println("结束"); // 编译异常 try { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); //Date date = sdf.parse("1999-10-10"); Date date = sdf.parse("1999年10月10日"); System.out.println(date); }catch (ParseException e){ System.out.println("发生了解析异常"); } System.out.println("结束"); } }
-
获取异常信息: ---->Throwable类
-
public String getMessage():获取异常的描述信息,原因(提示给用户的时候,就提示错误原因
-
public String toString():获取异常的类型和异常描述信息(不用)
-
public void printStackTrace():打印异常的跟踪栈信息并输出到控制台
/** * Created by PengZhiLin on 2021/8/6 11:22 */ public class Test1 { public static void main(String[] args) { // 运行异常 System.out.println("开始"); try{ System.out.println("try中发生异常前的代码"); System.out.println(1/0); //System.out.println(1/1); System.out.println("try中发生异常后的代码"); }catch (ArithmeticException e){ System.out.println("异常信息:"+e.getMessage()); System.out.println("异常类型和异常信息:"+e.toString()); System.out.println("异常类型和异常信息:"+e); e.printStackTrace(); } System.out.println("结束"); // 编译异常 try { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); //Date date = sdf.parse("1999-10-10"); Date date = sdf.parse("1999年10月10日"); System.out.println(date); }catch (ParseException e){ System.out.println("异常信息:"+e.getMessage()); System.out.println("异常类型和异常信息:"+e.toString()); System.out.println("异常类型和异常信息:"+e); e.printStackTrace(); } System.out.println("结束"); } }
-
5.4 finally 代码块
finally代码块的概述
finally:因为异常会引发程序跳转,导致有些语句执行不到。而finally就是解决这个问题的,在finally代码块中存放的代码在正常情况下一定会被执行的。
finally代码块的语法格式
try{
可能会出现异常的代码
}catch(异常的类型 变量名){
处理异常的代码或者打印异常的信息
}finally{
无论异常是否发生,都会执行这里的代码(正常情况,都会执行finally中的代码,一般用来释放资源)
}
执行步骤:
1.首先执行try中的代码,如果try中的代码出现了异常,那么就直接执行catch()里面的代码,执行完后会执行finally中的代码,然后程序继续往下执行
2.如果try中的代码没有出现异常,那么就不会执行catch()里面的代码,但是还是会执行finally中的代码,然后程序继续往下执行
注意:finally不能单独使用。
案例演示
/**
* Created by PengZhiLin on 2021/8/6 11:46
*/
public class Test {
public static void main(String[] args) {
// 快捷键: 选中代码块---->按ctrl+alt+t
System.out.println("开始");
try {
System.out.println(1);
System.out.println(1/0);// 发生异常
//System.out.println(1/1);// 不发生异常
System.out.println(2);
} catch (ArithmeticException e) {
System.out.println("发生了异常,异常的类型和信息:"+e);
return;// 结束方法,finally会执行
// System.exit(0);// 终止jvm,finally不会执行
} finally {
// finally中的代码正常情况无论是否发生异常都会执行,一般用来释放资源
System.out.println("finally中的代码...");
}
System.out.println("结束");
}
}
5.5 finally经典面试题
/**
* Created by PengZhiLin on 2021/8/6 11:53
*/
public class Test {
public static void main(String[] args) {
System.out.println(method1());// 30
System.out.println(method2());// 40
}
public static int method1() {
int num = 10;
try {
System.out.println(1 / 0);
num = 20;
} catch (ArithmeticException e) {
num = 30;
// 执行catch中的return语句会做2件事:
// 1.记录要返回的值,然后执行finally ---->记录的是30
// 2.返回之前记录的值,然后结束方法
return num;
} finally {
num = 40;
}
return num;
}
public static int method2() {
int num = 10;
try {
System.out.println(1 / 0);
num = 20;
} catch (ArithmeticException e) {
num = 30;
// 执行catch中的return语句会做2件事:
// 1.记录要返回的值,然后执行finally ---->记录的是30
// 第二步就执行不了了
return num;
} finally {
num = 40;
return num;
}
}
}
5.6 处理异常注意事项
-
try/catch/finally都不可以单独使用
-
运行时异常被抛出可以不处理(不捕获也不声明抛出),通过编译
-
在try/catch后可以追加finally代码块,其中的代码一定会被执行,通常用于资源回收
-
方法重写时的异常处理:
-
父类的方法声明处理异常,子类覆盖(重写)父类方法时,只能声明相同的异常或该异常子集
-
父类的方法未抛出的异常,子类覆盖(重写)父类方法时,只能捕获处理异常,不能声明处理异常
-
代码:
/** * Created by PengZhiLin on 2021/8/6 12:06 */ class Fu{ public void method1() throws FileNotFoundException, IOException { } public void method2(){ } } class Zi extends Fu{ //- 父类的方法声明处理异常,子类覆盖(重写)父类方法时,只能声明相同的异常或该异常子集 @Override public void method1() throws FileNotFoundException, IOException/*, ParseException 编译报错*/ { // 重写的method1方法中如果发生了解析异常,就得捕获处理 } //- 父类的方法未抛出的异常,子类覆盖(重写)父类方法时,只能捕获处理异常,不能声明处理异常 @Override public void method2() /*throws FileNotFoundException 编译报错*/{ // method2方法中发生的异常,只能捕获处理 } } public class Test1 { public static void main(String[] args) { } }
-
-
try…catch捕获多个异常的方式以及注意事项:
public class Test1 { public static void main(String[] args) { } // 捕获处理多个异常: 多次捕获多次处理 public static void method1(int num) { if (num == 10) { try { throw new FileNotFoundException("文件找不到异常"); } catch (FileNotFoundException e) { e.printStackTrace(); } } else { try { throw new IOException("IO异常"); } catch (IOException e) { e.printStackTrace(); } } } // 捕获处理多个异常: 一次捕获一次处理 public static void method2(int num) { try { if (num == 10) { throw new FileNotFoundException("文件找不到异常"); } else { throw new IOException("IO异常"); } } catch (IOException e) { e.printStackTrace(); } } // 捕获处理多个异常: 一次捕获多次处理 public static void method3(int num) { try { if (num == 10) { throw new FileNotFoundException("文件找不到异常"); } else { throw new IOException("IO异常"); } } catch (FileNotFoundException e) { // 处理文件找不到异常的代码 } catch (IOException e) { // 处理IO异常的代码 } } }
第六章 自定义异常
6.1 自定义异常
-
理解:在开发中根据自己业务的异常情况来定义异常类表示某种异常问题.
-
原因:Java中异常类具备异常发生中断程序的功能,但一些异常情况是java没有定义的,需要根据业务自行定义(例:年龄负数问题)
-
自定义异常类分类
-
自定义编译期异常: 自定义类 并继承于java.lang.Exception
-
自定义运行时期异常:自定义类 并继承于java.lang.RuntimeException
-
案例:
/** * Created by PengZhiLin on 2021/8/6 12:18 */ // 编译异常 public class MyException1 extends Exception { public MyException1() { } public MyException1(String message) { super(message); } } /** * Created by PengZhiLin on 2021/8/6 12:18 */ // 运行异常 public class MyException2 extends RuntimeException { public MyException2() { } public MyException2(String message) { super(message); } } /** * Created by PengZhiLin on 2021/8/6 12:18 */ public class Test1 { public static void main(String[] args) { // 创建自定义的编译异常对象 //throw new MyException1("编译异常"); // 创建自定义的运行异常对象 throw new MyException2("运行异常"); } }
-
-
需求:按照如下要求完成案例
-
模拟注册操作,如果用户名已存在,则抛出异常并提示:亲,该用户名已经被注册
/** * Created by PengZhiLin on 2021/8/6 12:21 */ // 运行异常 public class RegisterException extends RuntimeException { public RegisterException() { } public RegisterException(String message) { super(message); } }
/** * Created by PengZhiLin on 2021/8/6 12:21 */ public class Test2_练习 { public static void main(String[] args) { // 模拟注册操作,如果用户名已存在,则抛出异常并提示:亲,该用户名已经被注册 // 1.模拟数据库中已注册的用户名--->数组 String[] names = {"张三","李四","王五"}; // 2.用户输入用户名 Scanner sc = new Scanner(System.in); System.out.println("请输入要注册的用户名:"); String name = sc.next(); // 3.校验该用户名是否已经注册 for (String s : names) { if (s.equals(name)){ //注册了,就产生异常 throw new RegisterException("亲,该用户名已经被注册"); } } // 4.没有注册,就提示:恭喜,注册成功! System.out.println("恭喜,注册成功!"); } }
-
第七章 多线程
我们在之前,学习的程序在没有跳转语句的前提下,都是由上至下依次执行,那现在想要设计一个程序,边打游戏边听歌,怎么设计?
要解决上述问题,咱们得使用多进程或者多线程来解决.
7.1 并发与并行
- 并行:指两个或多个事件在同一时刻发生(同时执行)。
- 并发:指两个或多个事件在同一个时间段内发生(交替执行)。
7.2 线程与进程
-
进程:进程是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创建、运行到消亡的过程。每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程;
-
进程是应用程序的可执行单元也就是exe文件
-
一个应用程序可以有多个进程
-
每个进程执行都会有独立的内存空间
-
-
线程:是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一条线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。
- 线程是进程的可执行单元
- 一个进程可以有多条线程
- 每个线程执行都会有独立的内存空间
-
java只有单进程,然后有多线程
-
一个进程一次只能执行一条线程,所以java中只有多线程并发,没有多线程并行
-
线程的调度方式:
- 分时调度:所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间
- 抢占式调度:优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性)
- Java线程的调度方式: 抢占式
7.3 Thread类的api介绍
概述:
java.lang.Thread类代表**线程**,所有的线程对象都必须是Thread类或其子类的实例
每个线程的作用是完成一定的任务,实际上就是执行一段程序流即一段顺序执行的代码
Java使用线程执行体来代表这段程序流,在Tread线程中,使用run()方法代表线程执行体
构造方法
public Thread():创建一个新的线程对象,默认名称
public Thread(String name):创建一个指定名字的新的线程对象
public Thread(Runnable target):创建一个带有指定任务的线程对象,通过参数Runnable指定任务
public Thread(Runnable target,String name):创建一个带有指定任务的线程对象并指定线程名字
常用方法
public String getName():获取当前线程名称
public void start():导致此线程开始执行; Java虚拟机调用此线程的run方法
public void run():此线程要执行的任务在此处定义代码
public static void sleep(long millis):使当前正在执行的线程以指定的毫秒数暂停执行
public static Thread currentThread() :返回对当前正在执行的线程对象的引用
通过Thread类的api,可以指定创建线程有2种方式:
1.通过继承Thread类的方式
2.通过实现Runnable接口的方式
7.4 继承方式创建线程
-
步骤:
- 创建一个子类继承Thread类
- 在子类中重写run方法,把线程需要执行的任务代码放入run方法中
- 创建子类对象,调用start()方法启动线程,执行任务
-
实现:
/** * Created by PengZhiLin on 2021/8/6 15:24 */ public class MyThread extends Thread { @Override public void run() { // 线程的任务代码 for (int i = 0; i < 100; i++) { System.out.println("子线程:HelloWorld...." + i); } } }
/** * Created by PengZhiLin on 2021/8/6 15:24 */ public class Test { public static void main(String[] args) {// main方法在中主线程执行 // 创建线程对象 MyThread mt = new MyThread(); // 启动线程执行任务代码 mt.start(); // 主线程再打印100次HelloWorld for (int j = 0; j < 100; j++) { System.out.println("主线程:HelloWorld...." + j); } } }
7.5 实现方式创建线程
-
Runnable是一个任务接口,里面有一个抽象方法run(),可以在run方法中书写线程的任务代码
-
实现步骤:
- 创建实现类实现Runnable接口
- 在实现类中,重写run方法,把线程需要执行的任务代码放入run方法中
- 创建实现类对象
- 创建Thread线程对象,并传入实现类对象
- 使用Thread线程对象调用start方法启动线程,执行任务
-
实现:
/** * Created by PengZhiLin on 2021/8/6 15:45 */ public class MyRunnable implements Runnable { @Override public void run() { // 线程的任务代码 for (int i = 0; i < 100; i++) { System.out.println("子线程:HelloWorld..." + i); } } }
/** * Created by PengZhiLin on 2021/8/6 15:45 */ public class Test { public static void main(String[] args) { // 创建Runnable的实现类对象 MyRunnable mr = new MyRunnable(); // 创建Thread线程对象,传入实现类对象 Thread t = new Thread(mr); // 调用start方法启动线程,执行任务 t.start(); // 主线程任务 for (int j = 0; j < 100; j++) { System.out.println("主线程:HelloWorld..." + j); } } }
7.6 匿名内部类方式
-
原理: 可以传入Runnable接口的匿名内部类
-
步骤:
- 创建Thread线程对象,并传入Runnable接口的匿名内部类
- 在Runnable匿名内部类中重写run方法,书写线程需要执行的任务代码
- 使用Thread线程对象调用start方法启动线程,执行任务
-
实现:
/** * Created by PengZhiLin on 2021/8/6 15:50 */ public class Test { public static void main(String[] args) { // 1.创建Thread线程对象,并传入Runnable接口的匿名内部类 Thread t = new Thread(new Runnable() { @Override public void run() { // 2.在匿名内部类中重写run方法,书写线程任务代码 for (int i = 0; i < 100; i++) { System.out.println("子线程:HelloWorld..."+i); } } }); // 3.调用start方法启动线程,执行任务代码 t.start(); // 主线程任务代码 for (int j = 0; j < 100; j++) { System.out.println("主线程:HelloWorld..."+j); } } }
7.7 创建并启动多条线程
-
通过继承的方式:
/** * Created by PengZhiLin on 2021/8/6 15:56 */ public class MyThread extends Thread { public MyThread() { } public MyThread(String name) { super(name); } @Override public void run() { // 线程任务代码 System.out.println(getName()+"子线程:开始执行任务代码..."); // 暂停1000秒 try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(getName()+"子线程:结束执行任务代码..."); } }
/** * Created by PengZhiLin on 2021/8/6 15:56 */ public class Test { public static void main(String[] args) { // 创建并启动多条线程 MyThread mt1 = new MyThread("罗志祥"); MyThread mt2 = new MyThread("吴签"); MyThread mt3 = new MyThread("林俊杰"); MyThread mt4 = new MyThread("潘玮柏"); mt1.start(); mt2.start(); mt3.start(); mt4.start(); System.out.println("主线程的名称:"+Thread.currentThread().getName()); } }
-
通过实现的方式:
/** * Created by PengZhiLin on 2021/8/6 16:05 */ public class MyRunnable implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName() + "子线程:任务代码..."); } }
/** * Created by PengZhiLin on 2021/8/6 16:05 */ public class Test { public static void main(String[] args) { // 创建任务实现类对象 MyRunnable mr = new MyRunnable(); // 创建并启动多条线程 Thread t1 = new Thread(mr,"张柏芝"); Thread t2 = new Thread(mr,"李小璐"); Thread t3 = new Thread(mr,"白百何"); Thread t4 = new Thread(mr,"马蓉"); t1.start(); t2.start(); t3.start(); t4.start(); } }
7.8 实现方式创建线程的优势
实现Runnable接口比继承Thread类所具有的优势:
- 适合多个相同的程序代码的线程去共享同一个资源(任务)。
- 可以避免java中的单继承的局限性。
- 增加程序的健壮性,实现解耦操作,任务代码可以被多个线程共享,任务代码和线程独立。
- 线程池只能放入实现Runable或Callable类线程,不能直接放入继承Thread的类。
总结
必须练习:
1.创建并启动线程的三种方式---->必须掌握
2.创建并启动多条线程----->必须掌握
3.异常的处理(声明处理,捕获处理)---->alt+回车--->选择处理方式
4.冒泡排序和选择排序,二分查找要理解其原理,并做好笔记
5.预习
- 能够理解冒泡排序的执行原理
- 对要进行排序的数据中相邻的数据进行两两比较,将较大的数据放在后面
- 每一轮比较完毕,最大值在最后面,下一轮比较就少一个数据参与
- 每轮比较都从第一个元素(索引为0的元素)开始
- 依次执行,直至所有数据按要求完成排序
- 如果有n个数据进行排序,总共需要比较n - 1轮
- 能够理解选择排序的执行原理
- 对要进行排序的数组中,使某个元素依次和后面的元素逐个比较,将较大的数据放在后面
- 每一轮比较完毕,最小值在最前面,下一轮比较就少一个数据参与
- 每轮比较都从下一个(轮数+1)元素开始
- 依次执行,直至所有数据按要求完成排序
- 如果有n个数据进行排序,总共需要比较n - 1轮
- 能够理解二分查找的执行原理
- 每一次都去获取数组的中间索引所对应的元素,然后和要查找的元素进行比对,如果相同就返回索引
- 如果不相同,就比较中间元素和要查找的元素的值:
- 如果中间元素的值大于要查找的元素,说明要查找的元素在左侧,那么就从左侧按照上述思想继续查询(忽略右侧数据);
- 如果中间元素的值小于要查找的元素,说明要查找的元素在右侧,那么就从右侧按照上述思想继续查询(忽略左侧数据);
- 能够辨别程序中异常和错误的区别
- Error类(错误): 表示错误,不可以通过代码进行纠正使得程序继续运行,只能事先避免
- Exception类(异常):表示异常,可以通过代码进行纠正使得程序继续运行
- 说出异常的分类
- 编译异常: 程序在编译期间出现的异常,如果不处理,程序无法通过编译
- 运行异常: 程序在运行期间出现的异常,如果不处理,程序可以通过编译,但在运行的时候会出现异常
- 列举出常见的三个运行期异常
ArrayIndexOutOfBoundsException
NullPointerException
ClassCastException
...
- 能够使用try...catch关键字处理异常
格式,执行流程
- 能够使用throws关键字处理异常
格式,特点,使用场景
- 能够自定义并使用异常类
创建异常类继承Exception或者RuntimeException
- 说出进程和线程的概念
进程: 其实就是.exe文件
线程: 其实就是进程的可执行单元
- 能够理解并发与并行的区别
并发: 多个事件在同一时刻交替发生
并行: 多个事件在同一时刻同时发生
- 能够使用继承类的方式创建多线程
创建子类继承Thread类
在子类中重写run方法,把线程需要执行的任务代码放入run方法中
创建子类线程对象,调用start方法启动线程,执行任务
- 能够使用实现接口的方式创建多线程
创建实现类实现Runnable接口
在实现类中重写run方法,把线程需要执行的任务代码放入run方法中
创建Thread类线程对象,并传入任务对象
调用start方法启动线程,执行任务
- 能够说出实现接口方式的好处
1. 适合多个相同的程序代码的线程去共享同一个资源(任务)。
2. 可以避免java中的单继承的局限性。
3. 增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和线程独立。
4. 线程池只能放入实现Runable或Callable类线程,不能直接放入继承Thread的类。