高级主题

高级主题

线程协作

  • 生产者消费者模式:生产者和消费者共享同一个资源,并且生产者和消费者之间相互依赖,互为条件
    • 对生产者,没产品之前通知消费者等待;生产产品后,马上通知消费者
    • 对消费者,消费之后通知生产者消费结束,开始新的生产
  • synchronized不足以完成消费者生产者问题,只实现了同步,不能实现通信
  • 线程通信:java提供的几个通信方法
方法名 作用
wait() 表示线程一直等待,直到其他线程通知,会释放锁(对比sleep)
wait(long timeout) 指定等待的毫秒数
notify() 唤醒一个处于等待状态的线程
notifuAll() 唤醒同一个对象上所有调用wait()方法的线程,优先级高的先调度

解决方式1

并发协作模型“生产者/消费者模式”----管程法

  • 生产者:负责生产数据的模块(可能是方法、对象、线程、进程)
  • 消费者:负责处理数据的模块(可能是方法、对象、线程、进程)
  • 缓冲区:生产者投入缓冲区,消费者从缓冲区取出

//管程法:利用缓冲区
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;
    }
    //生产方法
    @Override
    public void run() {
        for (int i = 1; i < 20; i++) {
            System.out.println("生产了"+i+"只鸡");
            try {
                container.push(new Chicken(i));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class  Consumer extends Thread{
    SynContainer container;
    public Consumer(SynContainer container){
        this.container = container;
    }

    @Override
    public void run() {
        for (int i = 1; i < 20; i++) {
            try {
                System.out.println("消费了第"+container.pop().id+"只鸡");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

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) throws InterruptedException {
        //如果容器满了,等消费者消费
        if(count==chickens.length){
            //通知消费者,生产等待
            this.wait();
        }
        //没满,继续加入容器
        chickens[count] = chicken;
        count++;
        
        //通知消费者
        this.notify();
    }
    //消费者拿出产品
    public synchronized Chicken pop() throws InterruptedException {
        if (count==0){
            //等生产者生产,消费者等待
            this.wait();
        }
        //如果可以消费
        count--;
        Chicken chicken = chickens[count];

        //吃完了,返回吃完的鸡,通知生产者再生产
        this.notify();
        return chicken;
    }

}

解决方式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;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            if(i%2==0){
                tv.play("起飞");
            }else {
                tv.play("美甲的窃魂卷");
            }
        }
    }
}
//观众--消费者
class Watcher extends Thread{
    TV tv;

    public Watcher(TV tv) {
        this.tv = tv;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            tv.watch();
        }
    }
}
//节目--产品
class TV{
    String 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;
    }

}

线程池

  • 背景:处理并发情况下的线程,经常创建、销毁,影响性能
  • 思路:提前创建好多个线程,放入线程池,使用时直接获取,使用完放回池中(公共交通)
  • 好处:
    • 响应速度plus,资源消耗down
    • 便于管理:
      • corePoolSize:核心池大小
      • maximumPoolSize:最大线程数
      • keepAliveTime:线程没有任务时最多保存的时间
  • API:ExecutorService和Executors
    • ExecutorService:真正的线程池接口。常见子类ThreadPoolExecutor
方法 作用
void executor(Runnable command) 执行任务,没有返回值,一般用来执行Runnable
Futuresubmit(Callabletask) 执行任务,有返回值,一般用来执行Callable
void shutdown() 关闭连接池
    • Excutors:工具类、线程池的工厂类,用于创建并返回不同类型的线程池
    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{
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName());
        }
    }
    
    /*输出
    pool-1-thread-1
    pool-1-thread-2
    pool-1-thread-4
    pool-1-thread-3
    */
    
posted on 2022-06-13 09:53  NEK_SSY  阅读(41)  评论(0)    收藏  举报