多线程(续)
1.死锁
package com.tian.thread;//死锁:多个线程互相抱着对方需要的资源,然后形成僵持
public class DeadLock {public static void main(String[] args) {Makeup g1 = new Makeup(0,"灰姑娘");Makeup g2 = new Makeup(1,"白雪公主");g1.start();g2.start();}
}//口红
class Lipstick{}//镜子
class Mirror{}class Makeup extends Thread{static Lipstick lipstick = new Lipstick();static Mirror mirror = new Mirror();int choice;//选择String girlName;//使用化妆品的人Makeup(int choice , String girlName){this.choice =choice;this.girlName = girlName;}@Overridepublic void run() {//化妆try {makeup();} catch (InterruptedException e) {e.printStackTrace();}}//化妆,互相持有对方的债,就是需要拿到对方的资源private void makeup() throws InterruptedException {if (choice==0){synchronized (lipstick){//获得口红的债System.out.println(this.girlName+"获得口红的锁");Thread.sleep(1000);synchronized (mirror) {//一秒钟后获得镜子System.out.println(this.girlName+"获得镜子的锁");}}}else {synchronized (mirror){//获得镜子的债System.out.println(this.girlName+"获得镜子的锁");Thread.sleep(2000);synchronized (lipstick) {//二秒钟后获得口红System.out.println(this.girlName+"获得口红的锁");}}}}
}
解决方法:
package com.tian.thread;//死锁:多个线程互相抱着对方需要的资源,然后形成僵持
public class DeadLock {public static void main(String[] args) {Makeup g1 = new Makeup(0,"灰姑娘");Makeup g2 = new Makeup(1,"白雪公主");g1.start();g2.start();}
}//口红
class Lipstick{}//镜子
class Mirror{}class Makeup extends Thread{static Lipstick lipstick = new Lipstick();static Mirror mirror = new Mirror();int choice;//选择String girlName;//使用化妆品的人Makeup(int choice , String girlName){this.choice =choice;this.girlName = girlName;}@Overridepublic void run() {//化妆try {makeup();} catch (InterruptedException e) {e.printStackTrace();}}//化妆,互相持有对方的债,就是需要拿到对方的资源private void makeup() throws InterruptedException {if (choice==0){synchronized (lipstick){//获得口红的债System.out.println(this.girlName+"获得口红的锁");Thread.sleep(1000);}synchronized (mirror) {//一秒钟后获得镜子System.out.println(this.girlName+"获得镜子的锁");}}else {synchronized (mirror){//获得镜子的债System.out.println(this.girlName+"获得镜子的锁");Thread.sleep(2000);}synchronized (lipstick) {//二秒钟后获得口红System.out.println(this.girlName+"获得口红的锁");}}}
}
产生死锁的四个必要条件:
- 互斥条件:一个资源每次只能被一个进程使用
- 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放
- 不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺
- 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系
2.Lock锁
package com.tian.gaoji;import java.util.concurrent.locks.ReentrantLock;//测试Lock锁
public class TestLock {public static void main(String[] args) {TestLock2 testLock2 = new TestLock2();new Thread(testLock2).start();new Thread(testLock2).start();new Thread(testLock2).start();}
}class TestLock2 implements Runnable{int ticketNums = 10;//定义Lock锁ReentrantLock lock = new ReentrantLock();@Overridepublic void run() {while (true){try{lock.lock();//加锁if (ticketNums>0){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(ticketNums--);}else {break;}}finally {//解锁lock.unlock();}}}
}
3.生产者消费问题
3.1管程法
package com.tian.gaoji;//测试生产者消费者模型-->利用缓冲区解决:管程法//生产者;消费者;产品;缓冲区
public class TestPC {public static void main(String[] args) {SynContainer container = new SynContainer();new Productor(container).start();new Consumer(container).start();}
}//生产者
class Productor extends Thread{SynContainer container;public Productor(SynContainer container){this.container =container;}//生产@Overridepublic void run() {for (int i = 0; i < 100; i++) {container.push(new Chicken(i));System.out.println("生产了"+i+"只鸡");}}
}//消费者
class Consumer extends Thread{SynContainer container;public Consumer(SynContainer container){this.container = container;}//消费@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println("消费了-->"+container.pop().id+"只鸡");}}
}//产品
class Chicken{int id;//产品编号public Chicken(int id){this.id = id;}
}//缓冲区
class SynContainer{//需要一个容器大小Chicken[] chickens = new Chicken[10];//容器计数器int count = 0;//生产者放入产品public synchronized void push(Chicken chicken){//如果容器满了,就需要等待消费者消费if (count==chickens.length){//通知消费者消费,生产等待}//如果没有满,我们就需要丢入产品chickens[count]=chicken;count++;//可以通知消费者消费了}//消费者消费产品public synchronized Chicken pop(){//判断能否消费if (count==0){//等待生产者生产,消费者等待}//如果可以消费count--;Chicken chicken = chickens[count];//吃完了,通知生产者生产return chicken;}
}
3.2信号灯法
package com.tian.gaoji;//测试生产者消费者问题2:信号灯法,标志位解决
public class TestPC2 {public static void main(String[] args) {TV tv = new TV();new Player(tv).start();new Watcher(tv).start();}
}
//生产者-->演员
class Player extends Thread{TV tv;public Player(TV tv){this.tv = tv;}@Overridepublic void run() {for (int i = 0; i < 20; i++) {if(i%2==0){this.tv.play("快乐大本营播放中");}else {this.tv.play("抖音:记录美好生活");}}}
}
//消费者-->观众
class Watcher extends Thread{TV tv;public Watcher(TV tv){this.tv = tv;}@Overridepublic void run() {for (int i = 0; i < 20; i++) {tv.watch();}}
}
//产品-->节目
class TV{//演员表演,观众等待 T//观众观看,演员等待 FString voice;//表演的节目boolean flag = true;//表演public synchronized void play(String voice){if(!flag){try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("演员表演了:"+voice);//通知观众观看this.notifyAll();//通知唤醒this.voice =voice;this.flag =!this.flag;}//观看public synchronized void watch(){if (flag){try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("观看了:"+voice);//通知演员表演this.notifyAll();this.flag =!this.flag;}
}
4.线程池
package com.tian.gaoji;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;//测试线程池
public class TestPool {public static void main(String[] args) {//1.创建服务,创建线程池//newFixedThreadPool 参数为:线程池大小ExecutorService service = Executors.newFixedThreadPool(10);//执行service.execute(new MyThread());service.execute(new MyThread());service.execute(new MyThread());service.execute(new MyThread());//2.关闭链接service.shutdown();}
}
class MyThread implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName());}
}
5.总结
package com.tian.gaoji;import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;//回顾总结线程的创建
public class ThreadNew {public static void main(String[] args) {new MyThread1().start();new Thread(new MyThread2()).start();FutureTask<Integer> futureTask = new FutureTask<Integer>(new MyThread3());new Thread(futureTask).start();try {Integer integer = futureTask.get();System.out.println(integer);} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}}
}
//1.继承Thread类
class MyThread1 extends Thread{@Overridepublic void run() {System.out.println("MyThread1");}
}
//2.实现Runnable接口
class MyThread2 implements Runnable{@Overridepublic void run() {System.out.println("MyThread2");}
}
//3.实现Callable接口
class MyThread3 implements Callable<Integer>{@Overridepublic Integer call() throws Exception {System.out.println("MyThread3");return 100;}
}