Java面向对象程序设计 第九章总结



1. volatile关键字有什么作用

  • volatile意为不稳定的,提示编译器禁止对其修饰的数据进行优化。
  • 现代CPU工作时,先将数据从主存取出,加载到相应核心的寄存器中,再对其进行运算;而在多线程程序中,由于多核可见性受限,核心操作的是缓存中的副本,导致数据不同步。volatile关键字标识数据后,在程序运行时,该数据不加载到缓存中,直接操作主存中的数据。

2. 编写Java程序模拟烧水泡茶最优工序

/**
 * @title:泡茶程序模拟
 * @author YEE686
 * @version 20.11.10
 */
class ThreadA implements Runnable{
    Thread tb = new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("第1min:开始洗茶壶");
            try {
                Thread.sleep(600);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("第2min:洗茶壶完成\n" +"第2min:开始洗茶杯");
            try {
                Thread.sleep(2*600);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("第4min:洗茶杯完成\n"+"第4min:开始拿茶叶");
            try {
                Thread.sleep(5*600);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("第5min:拿茶叶完成\n线程2工作完成");
        }
    });

    @Override
    public void run() {

        System.out.println("第0min:开始洗水壶");
        try {
            Thread.sleep(600);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("第1min:洗水壶完成\n"+"第1min:开始烧水");
        tb.start();

        try {
            Thread.sleep(15*600);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("第16min:烧水完成\n"+"第16min:开始泡茶\n"+
                "线程1工作完成");
    }
}

public class Tea {
    public static void main(String[] args) {
        ThreadA tta = new ThreadA();
        Thread tea = new Thread(tta);
        tea.start();
        try{
            tea.join();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("泡茶完成");
        }
    }
}

泡茶运行效果


3. 编写Java程序模拟烧菜上菜流程

问题:各产生10个生产值和消费者线程,共享一个缓冲区队列,生产值线程将产品放入到缓冲区中,消费者从缓冲区取出产品。

/**
 * @title:烧菜上菜模拟
 * @author YEE686
 * @version 20.11.06
 */
class table {
    private volatile int dishes = 0;
    public static int MakeCounter = 0;
    public static int GetCounter = 0;

    synchronized public void makeDish() {
        if (dishes < 10) {
            dishes++;
            System.out.println(Thread.currentThread().getName()+
                    " 做了菜 "+dishes);
            notifyAll();
            MakeCounter++;
        } else {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    synchronized public void getDish() {
        if (dishes > 0) {
            System.out.println(Thread.currentThread().getName()+
                    " 拿了菜 "+dishes);
            dishes--;
            notifyAll();
            GetCounter++;
        } else {
            try{
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

class producer implements Runnable {
    table tb;

    @Override
    public void run() {
        for(int i=0; i<5; i++) {
            tb.makeDish();
        }
    }

    public void fetch(table tb) {
        this.tb = tb;
    }
}

class consumer implements Runnable {
    table tb;

    @Override
    public void run() {
        for(int i=0; i<5; i++) {
            tb.getDish();
        }
    }

    public void fetch(table tb) {
        this.tb = tb;
    }
}

public class Restaurant {
    public static void main(String[] args) {
        table tb = new table();
        producer pd = new producer();   pd.fetch(tb);
        consumer cn = new consumer();   cn.fetch(tb);

        Thread[] pr,cs;         //生产者线程组 消费者线程组
        pr = new Thread[10];    cs = new Thread[10];
        for(int i=0; i<10; i++) {
            pr[i] = new Thread(pd,"生产者"+i+"线程");
        }
        for(int i=0;i<10; i++) {
            cs[i] = new Thread(cn,"消费者"+i+"线程");
        }
        for(int i=0; i<10; i++) {
            pr[i].start();
            cs[i].start();
        }

        try{
            for(int i=0; i<10; i++) {
                pr[i].join();
                cs[i].join();
            }
        } catch (InterruptedException is) {
            is.printStackTrace();
        }

        System.out.println("一共做了"+table.MakeCounter+"道菜");
        System.out.println("一共拿了"+table.GetCounter+"道菜");
    }
}

存在问题1:最后打印数目不是50和50
存在问题2:会造成死锁
存在问题3:不清楚每个线程各生成和消费多少此



版权声明:本文为weixin_45750637原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。