1.死锁
>概述
不同的线程分别占用着对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁
一旦出现死锁,整个程序既不会放生异常,也不会给出任何提示,只是所有线程都处于阻塞状态,无法继续
>死锁的代码实现
public class _01_Deadlock_01 {
public static void main(String[] args) {
Thread t1 = new A();
Thread t2 = new A();
t1.setName("线程1");
t2.setName("线程2");
t1.start();
t2.start();
}
}
class A extends Thread {
static Object o1 = new Object();
static Object o2 = new Object();
@Override
public void run() {
if ("线程1".equals(getName())) {
synchronized (o1) {
System.out.println("o1被锁定");
synchronized (o2) {
System.out.println("o2被锁定");
}
}
}
else if("线程2".equals(getName())){
synchronized (o2) {
System.out.println("o2被锁定");
synchronized (o1) {
System.out.println("o1被锁定");
}
}
}
}
}
2.线程通信
>概述
1)为什么要处理线程通信?
当我们需要多个线程来共同完成一项任务,并且我们希望它们有规律的执行,那么多线程之间需要一些通信机制,来协调它们的工作,以此实现多线程共同操作一份数据
2)调用wait和notify方法需要注意的细节
-- wait方法与notify方法必须要有同一个锁对象调用,对应的锁对象可以通过notify唤醒使用同一个锁对象调用的wait方法后的线程
-- wait方法与notify是属于Object类的方法
-- wait方法和notify方法必须要在同步代码块或同步方法中使用
>使用案例
public class _04_Wait_01 {
public static void main(String[] args) throws InterruptedException {
Num num = new Num();
Thread t1 = new Thread(new PrintOdd(num));
Thread t2 = new Thread(new PrintEven(num));
t1.setName("打印奇数");
t2.setName("打印偶数");
t1.start();
Thread.sleep(100);
t2.start();
}
}
//打印奇数的类
class PrintOdd implements Runnable{
Num num;
public PrintOdd(Num num){
this.num = num;
}
@Override
public void run() {
while (true) {
num.printnum();
}
}
}
//打印偶数的类
class PrintEven implements Runnable{
Num num;
public PrintEven(Num num){
this.num = num;
}
@Override
public void run() {
while (true) {
num.printnum();
}
}
}
class Num{
private int count = 1;
public synchronized void printnum(){
System.out.println(Thread.currentThread().getName() + ":" + count);
//每次打印完自增1
count++;
notify();
try {
Thread.sleep(100);
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
>生产者与消费者问题
生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程,与此同时,消费者也在缓冲区中消耗这些数据,此问题的关键是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区空时消耗数据
详细介绍:https://www.cnblogs.com/ldddd/p/15770457.html
代码案例
public class Exer3 {
public static void main(String[] args) {
Cook c = new Cook();
Foodie f = new Foodie();
c.setName("厨师");
f.setName("吃货");
c.start();
f.start();
}
}
//消费者
class Foodie extends Thread{
@Override
public void run() {
while(true){
synchronized(Desk.lock){
//如果桌子上没有食物 就终止线程
if(Desk.count == 0){
break;
}else{
//判断桌子上是否有食物
if(Desk.FoodFlag == 0) { //如果没食物 就等待
try {
Desk.lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{ //如果有食物 就开吃
Desk.count--;
System.out.println("正在吃,还能吃" + Desk.count + "碗");
//修改桌子的状态
Desk.FoodFlag = 0;
Desk.lock.notifyAll();
}
}
}
}
}
}
//生产者
class Cook extends Thread{
@Override
public void run() {
while(true){
synchronized(Desk.lock){
//如果桌子上的食物满了 就终止线程
if(Desk.count == 0){
break;
}else{
//判断桌子上是否有食物
if(Desk.FoodFlag == 1){
//如果有 就等待
try {
Desk.lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{ //如果没有食物 就做
System.out.println("做了一碗饭");
//修改桌子的状态
Desk.FoodFlag = 1;
//等待消费者吃
Desk.lock.notifyAll();
}
}
}
}
}
}
//用于控制生产者和消费者的执行
class Desk{
//桌子上是否有食物 0没有 1有
public static int FoodFlag = 0;
//总个数
public static int count = 10;
//锁对象
public static Object lock = new Object();
}