生产者 消费者问题
两条线程一条作为生产者 一条作为消费者 生产者生产出产品,产生的产品放在缓存区之中
继承Object 的两个方法 wait() notify() 对应的线程通信的使用 一个是让线程进行等待 另一个是唤醒线程
具体生产者 消费者问题的解决方案
生产者与消费者必须要对应关系 生产的数目与消费的数目一致
两个线程调用同一个对象—对应的使用 synchronized关键字
关于等待和唤醒机制 在设立标志进行判断应该如何处理
public class TestPc2 {
public static void main(String[] args) {
TV tv = new TV();
Player player = new Player(tv);
Watcher watcher = new Watcher(tv);
player.start();
watcher.start();
}
}
//表演者
class Player extends Thread{
TV tv ;
public Player(TV tv) {
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
if (i % 2 == 0){
tv.playVideo("快乐大本营");
}
else{
tv.playVideo("抖音:热爱美好生活");
}
}
}
}
//观看视频的观众
class Watcher extends Thread{
TV tv = new TV();
public Watcher(TV tv) {
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
tv.watchVideo();
}
}
}
//视频的缓存舞台 即 TV
class TV{
//观众收看和表演节
boolean flag = true;
//确定逻辑
//F 观众收看 等待节目
//T 播放节目 观众等待
String Video;
public synchronized void playVideo(String Video){
if(!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("表演了"+Video);
this.Video = Video;
flag = !flag;
this.notifyAll();
}
//因为是多个线程操作同样一个对象tv所以使用synchronized方法锁住
public synchronized void watchVideo(){
if(flag){
try{
this.wait();
}catch (Exception e){
e.printStackTrace();
}
}
flag =!flag;
System.out.println("收看了" + Video);
this.notifyAll();
}
}
线程池 因为多余的线程是浪费资源 所以使用一个线程池 进行线程管理
线程池对应的操作是开启线程服务 执行线程 和关闭线程
开启线程池服务
ExecutorService作为接口 后使用 Executors创建线程池
ExecutorService service = Executors.newFixedThreadPool()
执行线程
service.execute(new Thread())
关闭线程池
service.shudown();
调用callable()接口是使用 submit 而 调用runnable实现类是使用execute23