创建多线程的三种方式
继承Thread类重写run方法,实现runnable接口重写run方法,实现callable接口重写call方法
Thread类中的start方法可以用来启动多线程,只要是实现了runnable接口的实例就可以放在Thread类的start方法中启动多线程。
runnable接口是一个函数式接口,可以用lambda表达式创建runnable的实例
lambda 表达式。只要接口中只有一个接口方法那就符合函数式接口,就可以用lambda表达式。
lambda表达式是去掉一些没有意义的代码块,把代码变得更加的简洁;
多线程中可以采用指定优先级让某个线程优先执行
多线程的安全性问题
多条线程对同一个对象操作时,如果不加入锁就可能出现安全性的问题。例如A和B两个人对同一个银行账户取钱,账户的余额是1000,A取800,B也取800,他们同时对该账户取钱,这时账户中的余额很有可能变成 -600。因为两个人同时取钱的时候看到的账户余额都是1000。两个人取的是800,800小于1000是有可能造成两人都会取到800,这时余额就是负的600,这时银行估计就哭了
所以解决安全性问题是要加锁的。
多线程状态
新生,就绪,运行,阻塞,死亡
操作多线程的方式
线程礼让不会造成阻塞;
线程睡眠sleep会造成线程阻塞;
线程中断 代码中定义到达某种条件就中断线程;
线程插队join会造成线程阻塞
线程锁
Synchronized的锁放在方法上锁的是this 本类对象实例。
Synchronized(object){代码块 } 可以锁任意对象实例。
Lock锁 要手动开启锁,释放锁;锁的是从开启锁到释放锁之间的代码块
出现死锁的情况:
当方法一 Synchronized代码块锁了A对象,然后嵌套一个Synchronized代码块锁B对象;
方法二 Synchronized代码块锁B对象然后再嵌套一个Synchronized代码块锁A;
这时就会出现死锁的情况,建议不要让Synchronized代码块中再嵌套Synchronized
线程的通信
wait 线程处于等待
notify 通知等待的线程可以进行了
管程法:需要有个缓冲区,让生产者 生产的资源放到缓冲区 ,消费者 消费缓冲区内的资源
生产者 生产资源,放到缓冲区,缓冲区有资源时通知消费者消费;缓冲区没有资源时让消费者等待,通知生产者 生产;缓冲区资源满时 让生产者等待通知消费者消费;
信号灯法:生产者 生产资源未被消费,声明一个flag标志相当于信号 信号为true时生产的资源已被消费,让消费者等待通知生产者生产,信号为false时生产的资源未被消费 让生产者等待,通知消费者消费