java开发的第十八个博客(线程通信与线程池)

1.线程通信

1.线程通信概念

  • 多个线程处理同一资源,但处理动作不同

2.为什么要进行线程通信

  • 因为CPU会随机切换,而我们要多个线程共同协作操作同一资源

3.如何通过线程通信使多个线程实现有效协作

  • 等待唤醒机制

2.等待唤醒机制

1.概念

  • 多个线程的协作机制,当一个线程完成指定操作就等待(wait),当其他线程完成其操作后将其唤醒(notify),必要时可以唤醒所有线程(notifyAll)

2.等待唤醒方法

  • public final void wait():通过锁对象使线程进入永久等待,等待唤醒
  • public final void wait(long timeout)通过锁对象使对象进入计时等待
  • public final void notify()唤醒该锁对象的一个等待线程
  • public final void notifyAll()唤醒该锁对象的所有等待线程

3.注意点

  • 即使唤醒了等待的线程,它也不一定会马上执行,因为它在同步块内,还需要获取锁才能继续执行

4.细节

  • 等待(wait)和唤醒(notify)必须要由同一锁对象调用,因为用A锁对象等待的线程,只能通过A锁对象才能唤醒
  • 等待(wait)和唤醒(notify)是属于Object类的,因为锁对象可以是任意对象
  • 等待(wait)和唤醒(notify)必须在同步代码块或者同步方法内使用,因为必须通过锁对象才能调用两个方法

5.生产者与消费者案例

import java.util.Random;

public class demo8 {
    public static void main(String[] args) {
        BaoZi bz = new BaoZi();
        BaoZiPu bzp = new BaoZiPu("包子铺",bz);
        ChiHuo ch = new ChiHuo("吃货", bz);
        bzp.start();
        ch.start();
    }
}
class BaoZi{//包子类
    private String pu;
    private String xian;
    private boolean flag;
    public String getPu() {
        return pu;
    }

    public String getXian() {
        return xian;
    }

    public boolean isFlag() {
        return flag;
    }

    public void setPu(String pu) {
        this.pu = pu;
    }

    public void setXian(String xian) {
        this.xian = xian;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }
}
class BaoZiPu extends Thread{//包子铺类
    private BaoZi bz;
    private int count;
    Random r = new Random();
    public BaoZiPu(String bzp, BaoZi bz) {
        super(bzp);
        this.bz = bz;
    }

    @Override
    public void run() {//生产包子
        while (true){
            synchronized (bz){
                if(bz.isFlag() == false){
                    if(r.nextInt(2)==0){
                        bz.setPu("面皮");
                        bz.setXian("韭菜");
                    }else {
                        bz.setPu("饺子皮");
                        bz.setXian("猪肉");
                    }
                    System.out.println(this.getName()+"做出了"+bz.getPu()+bz.getXian()+"包子");
                    bz.setFlag(true);
                    bz.notify();
                }else {
                    try {
                        bz.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            if(++count==100){
                break;
            }
        }
    }
}
class ChiHuo extends Thread {//吃货类
    private BaoZi bz;
    private int count;
    public ChiHuo(String ch, BaoZi bz) {
        super(ch);
        this.bz = bz;
    }
    @Override
    public void run() {//负责吃包子
        while (true) {
            synchronized (bz) {
                if (bz.isFlag() == true) {
                    System.out.println(this.getName() + "吃了" + bz.getPu() + bz.getXian() + "包子");
                    bz.setFlag(false);
                    bz.notify();
                } else {
                    try {
                        bz.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            if(++count==100){
                break;
            }
        }
    }
}

3.线程池

1.由来

  • 由于启动一个新线程成本较高,因其与操作系统交互,而使用线程池可较好的提高性能

2.概念

  • 一个容纳多个线程的容器,其中的线程可以反复使用

3.优点

  • 降低资源消耗,可重复使用线程
  • 提高响应速度,因为线程已经创建
  • 提高线程的可管理性,可以调整线程个数

4.线程池的使用

  • public static ExecutorService newFixedThreadPool(intnThreads)返回指定容量的线程池对象
  • public Future<?> submit(Runnable task或者Callabletast)获取线程池的某个线程对象并执行提交任务
  • 当submit方法参数为Callable接口实现类对象,重写的call方法有返回值,可通过Future未来对象的get方法来获取
  • ExecutorService 的void shutdown():关闭线程池

5.代码实例

import java.util.concurrent.*;
public class demo8 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
         A a = new A();//
        ExecutorService ex = Executors.newFixedThreadPool(1);//创建线程池对象
        Future<Boolean> submit = ex.submit(a);//执行线程并提交执行结果给Future类对象
        Boolean b = submit.get();//Future类对象获取返回值并接收
        ex.shutdownNow();//关闭线程池
    }
}
class A implements Callable<Boolean>{
    @Override
    public Boolean call() throws Exception {
        return true;//重写call方法
    }
}

上一篇:J-基础-线程-等待唤醒机制


下一篇:ITK:斑点Blob