Java【18】多线程(等待唤醒 wait、notify) 和泛型

一、多线程
1、线程间通信
(1)创建线程因为操作系统进行调度的,创建顺序不确定的,在程序通过条件控制,让线程执行有
顺序的,这个个过程--等待唤醒(通知)机制

(2)等待唤醒(通知)机制调用方法
第一个 wait() : 释放锁,需要被唤醒
第二个 notify()/notifyAll():通知其他线程
* 上面三个方法都是Object类里面的方法

(3)编写线程间通信例子
/**
 * 创建两个线程
 * 创建一个初始 变量 值是0
 * 实现一个线程对变量+1 ,另外一个线程对变量-1
 * 交替,进行10次
 */

2、线程其他概念
(1)线程生命周期
- 线程的生命周期有五种状态:新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)、死亡(Dead)。

(2)线程阻塞:
- 线程调用了sleep()方法,主动放弃所占用的CPU资源;
- 线程试图获取一个同步监视器,但该同步监视器正被其他线程持有;
- 线程执行过程中,同步监视器调用了wait(),让它等待某个通知(notify);
- 线程执行过程中,同步监视器调用了wait(time)
- 线程执行过程中,遇到了其他线程对象的加塞(join);

    public enum State {
        NEW,   新建
        RUNNABLE,  准备就绪
        BLOCKED,   阻塞
        WAITING,   不见不散
        TIMED_WAITING, 过时不候
        TERMINATED;    终结
    }

(3)Thread和Runnable区别
1. 适合多个相同的程序代码的线程去共享同一个资源。
2. 可以避免java中的单继承的局限性。
3. 增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和线程独立。
4. 线程池只能放入实现Runable或Callable类线程,不能直接放入继承Thread的类。

(4)释放锁操作
* 当前线程的同步方法、同步代码块执行结束。
* 当前线程在同步代码块、同步方法中遇到break、return终止了该代码块、该方法的继续执行。
* 当前线程在同步代码块、同步方法中出现了未处理的Error或Exception,导致当前线程异常结束。
* 当前线程在同步代码块、同步方法中执行了锁对象的wait()方法,当前线程被挂起,并释放锁。

(5)死锁
不同的线程分别锁住对方需要的同步监视器对象不释放,都在等待对方先放弃时就形成了线程的死锁。
一旦出现死锁,整个程序既不会发生异常,也不会给出任何提示,只是所有线程处于阻塞状态,无法继续。

(6)sleep()和wait()方法的区别
- sleep()不释放锁,wait()释放锁
- sleep()自动在指定时间唤醒,wait()可以指定时间也可以使用notify或notifyAll唤醒
- sleep()在Thread类中声明的静态方法,wait方法在Object类中声明


二、泛型
1、什么是泛型:
(1)在jdk1.5开始出现新特性,成为泛型
(2)使用泛型可以限定集合或者数组放什么类型数据,方法里面传递什么类型参数

2、演示泛型好处
(1)问题代码
public class GenericDemo1 {

    public static void main(String[] args) {
        //如果参数是字符串 abc,转换int类型出现异常 java.lang.ClassCastException
        add("abc",2);
    }

    public static void add(Object m,Object n) {
        //Object 强转 int
        int m1 = (Integer) m;
        int n1 = (Integer)n;
        System.out.println(m1+n1);
    }
}

(2)泛型解决问题
-  <自定义类型1,自定义类型2>  :使用大写字母代表自定义类型 <T,V>
-  <>可以写在类部分,写在方法部分

public class GengricDemo2 {

    public static void main(String[] args) {
        CompareData<Integer> compareData1 = new CompareData<Integer>(1,2);
        CompareData<Double> compareData2 = new CompareData<Double>(1.1,2.3);
    }
}

//泛型类
class CompareData<T> {
    //定义T类型属性
    private T a;
    private T b;

    //创建构造
    public CompareData(T a,T b) {
        int a1 = (Integer)a;
        int b1 = (Integer)b;
        System.out.println(a1+b1);
    }
}

3、泛型类和泛型接口
(1)泛型可以在类上面,或者接口上面使用
** <类型变量列表>中的类型变量不能用于静态成员上。

【修饰符】 class 类名<类型变量列表>{
    
}
public class User<T,V> {}

【修饰符】 interface 接口名<类型变量列表>{
    
}
public interface IDao<T,A> {}

(2)举例演示
public class GengricDemo3 {

    public static void main(String[] args) {
        //语文老师
        Student<String> student1 = new Student<String>("张无忌","优秀");

        //数学老师
        Student<Double> student2 = new Student<>("乔峰",60.1);

        //英语老师使用时:
        Student<Character> stu3 = new Student<Character>("张三", 'C');
    }
}

class Student<T> {
    private String name; //姓名
    private T score; //分数

    public Student() {
        super();
    }
    public Student(String name, T score) {
        super();
        this.name = name;
        this.score = score;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public T getScore() {
        return score;
    }

    public void setScore(T score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", score=" + score +
                '}';
    }
}

interface IDao<T> {
    public void add(T name);
}

class IDaoClass implements IDao<Double> {

    @Override
    public void add(Double name) {
        
    }
}

4、类型变量的上限
(1)语法: <类型变量  extends 上限>
 表示含义:类型变量是上限或者上限的子类

public class GenericDemo4 {

    public static void main(String[] args) {
        Stu<Integer> stu = new Stu<>(10);
    }
}

class Stu<T extends Integer> {
    private T score;
    
    public Stu(T score) {
        this.score = score;
        System.out.println(score);
    }
}

5、泛型擦除
(1)泛型在编译时候出现,编译之后没有泛型这个东西了
处理机制是通过类型擦除,擦除规则:

若泛型类型没有指定具体类型,用Object作为原始类型;
若有限定类型< T exnteds XClass >,使用XClass作为原始类型;
若有多个限定< T exnteds XClass1 & XClass2 >,使用第一个边界类型XClass1作为原始类型;


6、泛型方法
(1)在方法上面使用泛型
【修饰符】 <类型变量列表> 返回值类型 方法名(【形参列表】)【throws 异常列表】{
    //...
}
public static <T> void add(T a,T b) throws Exception {}

(2)举例演示
public class GenericDemo5 {

    public static void main(String[] args) {
        //getScore("优秀");
        getScore(100);
       // getScore('A');
    }

    public static <T extends Integer> void getScore(T score) {
        System.out.println(score);
    }
}


6、类型通配符?
当我们声明一个方法时,某个形参的类型是一个参数化的泛型类或泛型接口类型,
但是在声明方法时,又不确定该泛型实际类型,我们可以考虑使用类型通配符

package com.atguigu.generic;

public class GenericDemo6 {

    public static void main(String[] args) {
        //int类型
        StudentInfo<Integer> s1 = new StudentInfo<>("lucy",100);
        //字符串
        StudentInfo<String> s2 = new StudentInfo<>("mary","优秀");
        //字符类型
        StudentInfo<Character> s3 = new StudentInfo<>("jack",'B');
        
        //把上面三种不同类型数据放到一个数组里面
        //定义StudentInfo类型数组 泛型是通配符 ?
        StudentInfo<?>[] arr = new StudentInfo[3];
        //向数组放值
        arr[0]=s1;
        arr[1]=s2;
        arr[2]=s3;

        StudentInfoPrint.print(arr);
    }

}

class StudentInfoPrint {
    public static void print(StudentInfo<?>[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}

class StudentInfo<T>{
    private String name;
    private T score;

    public StudentInfo() {
        super();
    }
    public StudentInfo(String name, T score) {
        super();
        this.name = name;
        this.score = score;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public T getScore() {
        return score;
    }
    public void setScore(T score) {
        this.score = score;
    }
    @Override
    public String toString() {
        return "姓名:" + name + ", 成绩:" + score;
    }
}

7、类型通配符上限和下限
(1)上限
格式:<? extends E>

?  代表接收E类型或者E的子类型的元素
<? extends Number>

(2)下限
格式:<? super E>

? 代表接收E类型或者E的父类型的元素
<? super String>


三、数据结构入门
1、什么是数据结构
(1)多个数据存储特点(在内存如何存储的)
(2)多个数据之间关系体现出来

2、逻辑结构和物理结构

3、常用数据结构
(1)集合
(2)线性结构
(3)树形结构
(4)图形结构

4、数组存储结构特定
(1)连续的存储空间
(2)一次申请一大段连续的空间,一旦申请到了,内存就固定了。
(3)所有数据存储在这个连续的空间中,数组中的每一个元素都是一个具体的数据(或对象 地址),
所有数据都紧密排布,不能有间隔。
(4)数组查询方便

5、链表存储结构特点
(1)普通单链表:元素节点和执向下一个节点指针
(2)查询不方便,添加效率相对高

6、树形存储结构特点


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值