java基础复习05
java基础复习
面对对象
4.1、Debug追踪
Debug调试程序:
- 可以让代码逐行执行,查看代码执行的过程,调试程序中出现的bug
使用方式:
- 在行号的右边,鼠标左键单击,添加断点(每个方法的第一行,哪里有bug添加到哪里)右键,选择Debug执行程序
- 程序就会停留在添加的第一个断点处
执行程序:
-
f8: 逐行执行程序
-
f7: 进入到方法中
-
shift+f8: 跳出方法
-
f9: 跳到下一个断点,如果没有下一个断点,那么就结束程序
-
ctrl+f2:退出debug模式,停止程序
-
Console:切换到控制台
4.2、异常
异常: 指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。
在 java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象。Java处理异常的方式是中断处理。
throw关键字作用:
- 可以使用throw关键字在指定的方法中抛出指定的异常
使用格式:
if(判断语句){
throw new xxException(“异常产生的原因"");
}
注意:
-
throw关键字必须写在方法的内部
-
throw关键字后边new的对象必须是Exception或者Exception的子类对象
-
throwv关键字抛出指定的异常对象,我们就必须处理这个异常对象
-
throw关键字后边创建的是RuntimeException或者是RuntimeException的子类对象,我们可以不处理,默认交给JW处理(打印异常对象,中断程序)
-
throw关键字后边创建的是编译异常(写代码的时候报错),我们就必须处理这个异常,要么throws,要么try...catch
throws关键字
- 异常处理的第一种方式,交给别人处理
作用:
-
当方法内部抛出异常对象的时候,那么我们就必须处理这个异常对象
-
可以使用throws关键字处理异常对象,会把异常对象声明批出给方法的调用者处理(自己不处理,给别人处理),最终交给JWw处理-->中断处理
使用格式:在方法声明时使用
修饰符 返回值类型 方法名(参数列表) throws AAAExcepiton,BBBExcepiton. . .{
}
注意:
-
throws关键字必须写在方法声明处
-
throws关键字后边声明的异常必须是Exception或者是Exception的子类
-
方法内部如果抛出了多个异常对象,那么throws后边必须也声明多个异常
- 如果抛出的多个异常对象有子父类关系,那么直接声明父类异常即可
-
调用了一个声明抛出异常的方法,我们就必须的处理声明的异常
- 要么继续使用throws声明抛出,交给方法的调用者处理,最终交给JVM要么try...catch自己处理异常
try catch
格式:
try{
可能产生异常的代码
}catch(定义一个异常的变量,用来接收try中抛出的异常对象){
异常的处理逻辑,异常对象之后,怎么处理异常对象
一般在工作中,会把异常的信息记录到一个日志中
}
catch(异常类名变量名){}
注意:
-
try中可能绘抛出多个异常对象,那么就可以使用多个catch来处理这些异常对象
-
如果try中产生了异常,那么就会执行catch中的异常处理逻辑,执行完毕catch中的处理逻辑,继续执行try...catch之后的代码如果try中没有产生异常,那么就不会执行catch中异常的处理逻辑,执行完try中的代码,继续执行try. ..catch之后的代码
Finally代码块
格式:
try{
可能产生异常的代码
}catch(定义一个异常的变量,用来接收try中抛出的异常对象){
异常的处理逻辑,异常对象之后,怎么处理异常对象
一般在工作中,会把异常的信息记录到一个日志中
}
catch(异常类名变量名){
}finally{
无论是否出现异常都会执行
}
注意:
-
finally 不能单独使用,必须和try—起使用
-
finally 一般用于资源释放(资源回收),无论程序是否出现异常,最后都要资源释放(IO)
-
如果finally有return语句,永远返回finally中的结果,应该避免该情况。
4.3、多线程
并发:指两个或多个事件在同一个时问段内发生。(交替执行)
并行:指两个或多个事件在同一时刻发生(同时发生).(同时执行)
进程:
线程︰线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。(简而言之:一个程序运行后至少有一个进程,—个进程中可以包含多个线程)
线程调度
-
分时调度:
- 所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间。
-
抢占式调度:
- 优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为抢占式调度。
主线程:执行主(main)方法的线程
单线程程序: java程序中只有一个线程执行从main方法开始,从上到下依次执行
多线程程序
创建多线程程序的第一种方式:创建Thread类的子类
java.lang. Thread类:是描述线程的类,我们想要实现多线程程序,就必须继承Thread类
实现步骤:
-
创建一个Thread类的子类
-
在Thread类的子类中重写Thread类中的run方法,设置线程任务(开启线程要做什么?)
-
创建Thread类的子类对象
-
调用Thread类中的方法start方法,开启新的线程,执行run方法
- void start()使该线程开始执行;Java虚拟机调用该线程的run方法。
- 结果是两个线程并发地运行;当前线程(main线程)和另一个线程(执行其 run方法)。
- 多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。
public class MyThread extends Thread{ //1.创建一个Thread类的子类
@Override
public void run() { //2.在Thread类的子类中重写Thread类中的run方法,设置线程任务(开启线程要做什么?)
for (int i = 0; i < 20; i++) {
System.out.println("run:"+i);
}
}
}
public class DemoThread {
public static void main(String[] args) {
MyThread mt = new MyThread();//3.创建Thread类的子类对象
mt.start();//4.调用Thread类中的方法start方法,开启新的线程,执行run方法
for (int i = 0; i < 20; i++) {
System.out.println("main:"+i);
}
}
}
创建多线程程序的第二种方式:实现Runnable接口 java.Lang . Runnable
实现步骤:
1、创建一个Runnable接口的实现类
2、在实现类中重写Runnable接口的run方法,设置线程任务
3、创建一个Runnable接口的实现类对象
4、创建Thread类对象,构造方法中传递Runnable接口的实现类对象
5、调用Thread类中的start方法,开启新的线程执行run方法
public class RunnableImpl implements Runnable{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName()+"--->"+i);
}
}
}
public class DemoRunnable {
public static void main(String[] args) {
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName()+"--->"+i);
}
RunnableImpl ra = new RunnableImpl();
Thread th = new Thread(ra);
th.start();
}
}
Thread常用方法
public static void sleep(Long millis):使当前正在执行的线程以指定的毫秒数暂停〈暂时停止执行)。
public class DemoThread01 {
public static void main(String[] args) {
for (int i = 0; i <20 ; i++) {///模拟秒表
System.out.println(i);
try {
Thread.sleep(1000);//使用Thread类的sleep方法让程序睡眠1秒钟
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
匿名内部类方式实现线程的创建
匿名内部类作用:简化代码
- 把子类继承父类,重写父类的方法,创建子类对象合一步完成
把实现类实现类接口,重写接口中的方法,创建实现类对象合成一步完成
匿名内部类的最终产物:子类/实现类对象,而这个类没有名字
格式:
new 父类/接口(){
重复父类接口中的方法
};
public class Demo01 {
public static void main(String[] args) {
new Thread() {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName()+"+"+i);
}
}
}.start();
}
}
public class Demo02 {
public static void main(String[] args) {//用接口的方式
Runnable r = new Runnable(){
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName()+"+程序员");
}
}
};
new Thread(r).start();
}
}
4.4、线程安全
多线程在用到相同资源时会产生安全问题
解决方法
-
同步代码块。
-
同步方法。
-
锁机制。
同步代码块:synchronized关键字可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。
格式:
synchronized(同步锁){
//需要操作的代码
}
注意:
-
通过代码块中的锁对象,可以使用任意的对象
-
但是必须保证多个线程使用的锁对象是同一个
-
锁对象作用:
- 把同步代码块锁住,只让一个线程在同步代码块中执行
public class RunnableImpl implements Runnable{
private int ticket = 100;
Object object = new Object();
@Override
public void run() {
while (true) {
synchronized (object) {
if (ticket > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "--->正在卖第:" + ticket + "张票");
ticket--;
}
}
}
}
}
public class DemoMain {
public static void main(String[] args) {
RunnableImpl runnable = new RunnableImpl();
Thread t1 = new Thread(runnable);
Thread t2 = new Thread(runnable);
Thread t3 = new Thread(runnable);
t1.start();
t2.start();
t3.start();
}
}
同步方法
-
把访问了共享数据的代码抽取出来,放到一个方法中
-
在方法上添加synchronized修饰符
格式:
修饰符 synchronized 返回值类型 方法名(参数列表){
可能会出现线程安全问题的代码(访问了共享数据的代码)
}
public class RunnableImpl implements Runnable {
private int ticket = 100;
@Override
public void run() {
while (true) {
payTicket();
}
}
public synchronized void payTicket() {
if (ticket > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "--->正在卖第:" + ticket + "张票");
ticket--;
}
}
}
锁机制
使用Lock锁 java.util.concurrent.tocks.Lock接口
Lock实现提供了比使用synchronized 方法和语句可获得的更广泛的锁定操作。
Lock接口中的方法:
-
void lock() 获取锁。
-
void unlock() 释放锁。
public class RunnableImpl implements Runnable {
private int ticket = 100;
Lock l = new ReentrantLock();
@Override
public void run() {
while (true) {
l.lock();
if (ticket > 0) {
try {
Thread.sleep(10);
System.out.println(Thread.currentThread().getName() + "--->正在卖第:" + ticket + "张票");
ticket--;
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
l.unlock();
}
}
}
}
}
4.5、等待唤醒机制
等待唤醒案例:线程之间的通信
创建一个顾客线程(消费者):告知老板要的包子的种类和数量,调用wait方法,放弃cpu的执行,进入到waiting状态(无限等待)
创建一个老板线程(生产者):花了5秒做包子,做好包子之后,调用notify方法,唤醒顾客吃包子
注意:
-
顾客和老板线程必须使用同步代码块包裹起来,保证等待和唤醒只能有一个在执行
-
同步使用的锁对象必须保证唯一
-
只有锁对象才能调用wait和notify方法
public class DemoWaitAndNotify {
public static void main(String[] args) {
Object o = new Object();
new Thread() {
@Override
public void run() {
synchronized (o){
System.out.println("告诉老板要的包子的数量和种类");
try {
o.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("包子已经做好了 ,开吃");
}
}
}.start();
new Thread(){
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (o){
System.out.println("老板五秒后做好包子,告诉顾客可以吃了");
o.notify();
}
}
}.start();
}
}
进入到Timewaiting(计时等待)有两种方式
-
使用sleep(Long m)方法,在毫秒值结束之后,线程睡醒进入到Runnable/BLocked状态
-
使用wait(Long m)方法, wait方法如果在毫秒值结束之后,还没有被notify响醒,就会自动醒来,线程睡醒进入到RunnabLe/BLoched状态
唤醒的方法:
-
void notify()唤醒在此对象监视器上等待的单个线程。
-
void notifyAll()唤醒在此对象监视器上等待的所有线程。
吃包子案例
public class BaoZi {
String pi;
String xian;
Boolean flat =false;
}
public class BaoZiPu extends Thread{
private BaoZi bz;
public BaoZiPu(BaoZi bz) {
this.bz = bz;
}
@Override
public void run() {
while (true) {
synchronized (bz) {
if (bz.flat == false) {
try {
bz.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("吃货正在吃:" + bz.pi + "、" + bz.xian + "的包子");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
bz.flat = false;
bz.notify();
System.out.println("已经把:" + bz.pi + "、" + bz.xian + "的包子吃完了,包子铺快继续生产");
System.out.println("----------------------------------");
}
}
}
}
public class ChiHuo extends Thread{
private BaoZi bz;
public ChiHuo(BaoZi bz) {
this.bz = bz;
}
@Override
public void run() {
int count = 0;
while (true) {
synchronized (bz) {
if (bz.flat == true) {
try {
bz.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (count % 2 == 0) {
bz.pi = "薄皮";
bz.xian = "猪肉";
} else {
bz.pi = "冰皮";
bz.xian = "牛肉";
}
count++;
System.out.println("包子铺正在生产:" + bz.pi + "、" + bz.xian + "的包子");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
bz.flat = true;
bz.notify();
System.out.println("包子铺已经生产好了:" + bz.pi + "、" + bz.xian + "的包子,可以开吃了!");
}
}
}
}
public class Demo {
public static void main(String[] args) {
BaoZi bz = new BaoZi();
new BaoZiPu(bz).start();
new ChiHuo(bz).start();
}
}
原文地址:https://www.cnblogs.com/webclub/p/15086573.html
- JAVA利用jxl读取Excel内容
- JAVA利用jxl读取Excel内容
- 【java开发系列】—— 自定义注解
- CSS 特殊属性介绍之 pointer-events
- 【java开发系列】—— 集合使用方法
- Elasticsearch安装
- 【java开发系列】—— 深克隆和浅克隆
- 【java开发系列】—— JDOM创建、修改、删除、读取XML文件
- AngularJs ng-route路由详解
- JAVA获取txt文件内容
- 关于 CSS 反射倒影的研究思考
- 【Javascript】—— 1 方法function的高级特性
- Oracle基础知识-SQL简单命令
- 【java开发系列】—— spring简单入门示例
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 数据结构之树
- UNIX网络编程卷1(第三版)套接字编程简介
- UNIX网络编程卷1(第三版)readn,writen和readline函数
- UNIX网络编程卷1(第三版)基本TCP套接字编程
- Ubuntu下linux映射共享盘到window下方法
- 数据同步写入磁盘:sync
- 惯用的关机命令:shutdown
- 重启、关机:reboot,halt,poweroff
- 使用Docker构建ZooKeeper镜像
- Linux进程间的通信
- 如何使用jMeter对需要CSRF token验证的OData服务进行并发性能测试
- 如何让SAP C4C自定义BO实现附件上传的功能
- SAP C4C基于自定义BO开发的OWL UI,如何实现动态访问控制
- 使用ABAP CL_HTTP_CLIENT类消费OData服务时,如何避免CSRF令牌验证失败错误
- 使用ABAP代码消费SAP Cloud for Customer的OData服务