java基础复习05

时间:2021-08-01
本文章向大家介绍java基础复习05,主要包括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