线程-集合-反射

线程

注意!java并不能直接开启线程,java无法操作硬件,查看thread源码可以知道,它是通过调用一个本地c++方法实现的。

实现方式
  • 通过继承thread类实现(拓展性不强,继承thread后就不能继承其他类了)

  • 通过实现Runnable接口实现

  • 实现callable类(企业级开发中常用,特点是重写的call()方法有返回值,有利于异常处理)

如何使用?
  1. 自定义类继承thread类或实现接口
  2. 重写run方法,编写执行体
  3. 新建线程实例,start()启动
//继承Thread类启动
Thread thread = new Thread(线程类);	  //创建线程实例
thread.setName("线程名称");				  //一种规范
thread.start();							//启动

//实现Runnable接口启动
new Thread(传入对象,"线程名称").start();		//启动
并行与并发
  • 并行:多人同行,多个线程同时执行,多核处理

  • 并发:多个线程调用一个资源,通过快速交替执行模拟并行状态

线程与进程
  • 进程:如qq,微信,Typora等

  • 线程:比如Typora里定时自动更新的功能便是线程实现

  • 一个进程包括多个线程,至少一个,java默认两个线程,main线程与GC线程

线程的五个状态

创建,就绪,运行,阻塞,死亡

在这里插入图片描述

new					#创建
runnable			#执行
blocked				#阻塞
waiting				#等待(等到为止)
time_waiting		#超时等待(超过时间不再等待)
terminated			#终止

Thread.getstate()	#获取线程状态,以上6个
while(thread.getstate() != Thread.State.TERMINATED);		#注意TERMINATED状态的线程无法再次启动
wait/sleep
  • wait:等待会释放锁,只能在同步代码块中使用(加锁的方法),继承object类,需要捕获异常
  • sleep:抱着锁睡觉,不会释放锁,在哪里都可以睡,继承至thread类
  • 企业级开发中并不使用sleep,而是调用JUC的timeUnit方法
线程礼让yield
  • 将线程的运行状态改为就绪状态
  • 礼让不一定成功,看cpu心情
  • 方法Thread.yield()
线程插队Join
  • 插入线程后,执行完该线程再恢复原来的状态,如同插队打饭
  • 方法Thread.yield()
线程优先级
  • 使用数字1~10表示线程的优先级,默认优先级为5
  • getPriority()和setPriiority()提供对线程的优先级获取和设置的方法
  • 注意优先级高的不是一定先执行,而是增加了先执行的概率,优先级的设置建议在start前
守护线程
  • 线程分用户线程(如main线程,默认线程都是守护线程)和守护线程(如gc垃圾回收线程)
  • 虚拟机必须确保用户线程执行结束,而不需要等待守护线程结束
  • thread.setDaemon(true)设置为守护线程,默认false用户线程,start前设置
  • 守护线程常用于日志,监控内存,垃圾回收等
线程同步
  • 一个对象被多个线程访问,即线程同步
  • 保证并发安全性条件:队列+锁
  • 实现线程同步使用排队机制,创建等待池
synchronized 锁(同步方法)
  • 加锁能保证安全性,但降低了性能,且破坏线程的优先级
  • 使用synchronized锁的是this,或者说class,我们往往需要锁的是对象,建议使用同步块synchronized(obj){ },这里obj是要上锁的对象,被称之为同步监视器。
Lock锁
  • jdk5开始出现的方法,继承于JUC

  • 相比于隐式锁synchronized,lock锁是显示的,手动进行加锁解锁

  • lock锁运行效率上高于synchronized,且有很多子类,有更好的拓展性

  • lock是代码块锁,不能对方法或者类上锁

  • ReentrantLock可重入锁的使用

    public TestLock implements Runnable{
        //票的总数
        private tickNums = 10;
        //定义lock锁
        private final ReentrantLock lock = new ReentrantLock();
        
        @Override
        public void run() {
            while (true) {
                try {
                    lock.lock();		//加锁
                    Thread.sleep(1000)	//休眠1秒
                    System.out.println(tickNums--);
                } finally {
                    lock.unlock();		//解锁
                }
            }
        }
    }
    
线程协调(生产者消费者问题)
  • 管程法:创建缓冲区,充当仓库的角色,产品不足通知生产者,有了产品通知消费者

  • 信号灯法:设置标识符,通过状态通知生产者消费者

  • 常用关键字

    wait()				//释放资源开始等待,进入等待池
    wait(long timecut)	//指定时间等待,单位毫秒
    notify()			//随机唤醒一个等待池(同一个对象上调用wait()方法的中的线程
    notifyAll()			//唤醒同一个对象上所有调用wait()方法的线程,根据优先级调用
    
线程并发库
  • 目的是设置线程数量上限,防止线程过多导致缓慢或崩溃,线程池控制线程的创建与销毁

  • 创建线程池有常用的四种线程池,通过JUC的Excutors提供方法

    newFixdThreadPool()			//指定最大并发数,超出的在队列中等待
    newCachedThreadPool()		//可缓冲线程池,长久不用的(60s)自动回收
    newScheduledThreadPool()	//指定最大并发数,可执行周期性,定时性任务执行
    newSingleThreadExecutor()	//单线程化的线程池
    
  • 线程池使用方式

    ExecutorService service = Excutors.newFixdThreadPool(10)			//创建线程池连接,包含10个线程
    
    //执行
    service.excute(new Mythread());
    service.excute(new Mythread2());
    .......
        
    service.shutdown();													//关闭连接
    

集合

存放对象的容器,容量可变,注意集合里存放的都是对象的引用,不能存放基本数据类型,基本数据类型要进行包装后才能存入。

集合框架

在这里插入图片描述

Collection

储存的都是value类型的

List

有序的,有下标,可重复,可为null

  • ArrayList

    • 底层是数组实现,可自动扩容,一般是装满0.75扩容0.5倍

    • 查询,修改效率高,插入,删除效率低

    • 默认是线程不安全的,可以设置为线程安全

      List lsit = Collections.synchronizedList(new ArrayList());

  • LinkedList

    • 底层用双向链表实现的

    • 插入,删除高效,查询,修改低效

    • 线程不安全的

  • Vector

    • 向量,可以理解为ArrayList()的同步实现
Set

不可重复

  • HashSet

    • 底层使用HashMap实现的
    • 无序,可有一个null
    • 初始容量16
  • TreeSet

    • 底层使用TreeMap实现的
    • 插入时排序,不可为null
    • 一个不同步的非线程安全的二叉树
Map

存放key-value类型的键值对

HashMap
  • 底层由Hash表(数组结构)+链表实现的,jdk8后,默认长度为8时实现红黑树可排序

  • key无序的,不可重复,可有一个null,value无限制(判断key重复先比hashCode值,再调用equals()对比内容)

  • 默认线程不安全的

  • HashTable与Hashmap类似,是线程安全的,但效率会降低

  • ConcurrentHashMap是用两者实现的,线程安全且效率高

TreeMap
  • 底层通过红黑树实现
  • 默认key自然顺序排序,不可重复,不能为null
  • 可被克隆,可序列化

反射

所有框架底层的实现机制就是反射+注解

概述
  • 理解:
    在这里插入图片描述

  • java作为一门静态语言,因为有了反射,让它可以实现动态语言的功能,让java变成一门准静态语言

  • 使用反射机制,允许我们在程序执行期间操作类的内部信息,包括私有化属性,方法(所以java不存在真正意义上的封装)

  • 反射会消耗大量的性能,大概是new的几十倍,使用需要谨慎

Class
  • 不管创建多少个类的实例,jvm中都只有一个它的Class,例如我们写了一个类,如果没有new一个对象实例化,是没有生成.class文件的,只有我们程序中实例化了对象,且不管实例化多少个,都只有一个对应的.class文件。

  • 通过Class可以获得这个类的所有内部信息,结构

  • 几乎所有类型都有Class对象,包括接口,[]数组,enum枚举,注解,基本数据类型,甚至void都有Class对象

  • 获取Class实例

    //com.howe.entity下定义一个Student类继承Person类
    Person person = new Student();
    
    //方法一:通过实例对象获取Class
    Class c1 = person.getClass();
    
    //方法二:通过forname获取Class
    Class c2 = Class.forname("com.howe.entity.Student");		//需要抛出异常
        
    //方法三:通过类名.class属性获取
    Class c3 = Student.class;
    
    //方法四:一些类(如基本数据类型的封装类)可以通过.TYPE获取
    Class c4 = Integer.TYPE
        
    //获取Class父类的Class
    Class c5 = c1.getSuperclass();
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值