Day16-Java进阶-线程通信&线程生命周期&线程池&单例设计模式

1. 线程通信

1.1 线程通信介绍

1.2 两条线程通信

package com.itheima.correspondence;

public class CorrespondenceDemo1 {
    /*
        两条线程通信
     */
    public static void main(String[] args) {
        Printer1 p = new Printer1();

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (Printer1.class) {
                    while (true) {
                        try {
                            p.print1();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (Printer1.class) {
                    while (true) {
                        try {
                            p.print2();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }).start();
    }

}

class Printer1 {

    int flag = 1;

    public void print1() throws InterruptedException {

        if (flag!=1){
            // 等待线程2
            Printer1.class.wait();
        }

        System.out.print("传");
        System.out.print("智");
        System.out.print("教");
        System.out.print("育");
        System.out.println();

        flag = 2;
        // 唤醒线程2
        Printer1.class.notify();
    }

    public void print2() throws InterruptedException {

        if (flag != 2) {
            // 等待线程1
            Printer1.class.wait();
        }

        System.out.print("黑");
        System.out.print("马");
        System.out.print("程");
        System.out.print("序");
        System.out.print("员");
        System.out.println();

        flag = 1;
        // 唤醒线程1
        Printer1.class.notify();
    }
}

1.3 三条线程通信

对于三条线程通信, 使用notifyAll(), 唤醒所有进程以避免死锁

package com.itheima.correspondence;

public class CorrespondenceDemo2 {
    /*
        三条线程通信

        问题: sleep方法和wait方法的区别?
        回答:
                sleep方法是线程休眠, 时间到了自动醒来, sleep方法在休眠的时候, 不会释放锁.
                wait方法是线程等待, 需要由其它线程进行notify唤醒, wait方法在等待期间, 会释放锁.
     */
    public static void  main(String[] args) {

        Printer2 p = new Printer2();

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (Printer2.class) {
                    while (true) {
                        try {
                            p.print1();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (Printer2.class) {
                    while (true) {
                        try {
                            p.print2();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (Printer2.class) {
                    while (true) {
                        try {
                            p.print3();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }).start();

}
}


class Printer2 {

    int flag = 1;

    public void print1() throws InterruptedException {

        if (flag != 1) {
            Printer2.class.wait();
        }
        System.out.print("传");
        System.out.print("智");
        System.out.print("教");
        System.out.print("育");
        System.out.println();

        flag = 2;
        Printer2.class.notifyAll();

    }

    public void print2() throws InterruptedException {

        if (flag != 2) {
            Printer2.class.wait();
        }
        System.out.print("黑");
        System.out.print("马");
        System.out.print("程");
        System.out.print("序");
        System.out.print("员");
        System.out.println();

        flag = 3;
        Printer2.class.notifyAll();
    }

    public void print3() throws InterruptedException {

        if (flag != 3) {
            Printer2.class.wait();
        }
        System.out.print("传");
        System.out.print("智");
        System.out.print("大");
        System.out.print("学");
        System.out.println();

        flag = 1;
        Printer2.class.notifyAll();
    }
}

1.4 三条线程通信的优化

package com.itheima.correspondence;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class CorrespondenceDemo3 {
    /*
        三条线程通信 - 优化:
                将同步信号synchronized换成ReentrantLock
     */
    public static void main(String[] args) {

        Printer3 p = new Printer3();

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        p.print1();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        p.print2();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        p.print3();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

    }
}

class Printer3 {

    ReentrantLock lock = new ReentrantLock();

    Condition c1 = lock.newCondition();
    Condition c2 = lock.newCondition();
    Condition c3 = lock.newCondition();

    int flag = 1;

    public void print1() throws InterruptedException {

        // 上锁
        lock.lock();

        if (flag != 1){
            // 线程1等待, c1绑定线程1
            c1.await();
        }

        System.out.print("传");
        System.out.print("智");
        System.out.print("教");
        System.out.print("育");
        System.out.println();

        flag = 2;
        c2.signal();

        // 解锁
        lock.unlock();

    }

    public void print2() throws InterruptedException {

        lock.lock();

        if (flag != 2){
            // 线程2等待, c2绑定线程2
            c2.await();
        }

        System.out.print("黑");
        System.out.print("马");
        System.out.print("程");
        System.out.print("序");
        System.out.print("员");
        System.out.println();

        flag = 3;
        c3.signal();

        lock.unlock();
    }

    public void print3() throws InterruptedException {

        lock.lock();

        if (flag != 3){
            // 线程3等待, c3绑定线程3
            c3.await();
        }

        System.out.print("传");
        System.out.print("智");
        System.out.print("大");
        System.out.print("学");
        System.out.println();

        flag = 1;
        c1.signal();

        lock.unlock();
    }
}

1.5 案例-生产消费模式

package com.itheima.producer_consumer;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class WareHouse {
    /**
     * 缓冲区域
     */
    public static boolean mark = false;
    public static ReentrantLock lock = new ReentrantLock();
    public static Condition producer = lock.newCondition();
    public static Condition consumer = lock.newCondition();


}
package com.itheima.producer_consumer;

public class Producer implements Runnable {
    /*
        生产者
     */

    @Override
    public void run() {
        while (true) {
            WareHouse.lock.lock();
            if (WareHouse.mark){
                try {
                    WareHouse.producer.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("生产者线程生产了包子...");
            WareHouse.mark = true;
            WareHouse.consumer.signal();
            WareHouse.lock.unlock();
        }
    }
}
package com.itheima.producer_consumer;

public class Consumer implements Runnable{
    /*
        消费者
     */

    @Override
    public void run() {
        while (true) {
            WareHouse.lock.lock();
            if (!WareHouse.mark){
                try {
                    WareHouse.consumer.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("消费者吃了包子...");
            WareHouse.mark = false;
            WareHouse.producer.signal();
            WareHouse.lock.unlock();
        }
    }
}
package com.itheima.producer_consumer;

public class Test {
    /*
        测试类
     */
    public static void main(String[] args) {
        new Thread(new Producer()).start();
        new Thread(new Consumer()).start();
    }
}

2. 线程生命周期

注: 面试时最好能画出来

3. 线程池

~见Day15最后一节

4. 单例设计

4.1 单例设计-饿汉式

package com.itheima.single_design;

public class SingleDesignDemo1 {
    /*
        单例设计模式 - 饿汉式(推荐使用, 简单不复杂)

        -----------------------------------------------------------------

        class Single1 {
            private Single1() {
            }

            public static final Single1 s = new Single1();
        }

        -----------------------------------------------------------------
     */
    public static void main(String[] args) {
        
        Single1 s = Single1.getInstance();

        System.out.println(s);
    }
}

class Single1 {
    private Single1() {
    }

    private static Single1 s = new Single1();

    public static Single1 getInstance() {
        return s;
    }
}

4.2 单例-懒汉式(延迟加载模式)

package com.itheima.single_design;

public class SingleDesignDemo2 {
    /*
        单例设计模式 - 懒汉式 (延迟加载模式) --- 面试时可能会问到

        --------------------------------------------------

            class Single2 {

                private Single2() {
                }

                private static Single2 s;

                public static Single2 getInstance() {
                    if (s == null) {
                        s = new Single2();
                    }
                    return s;
                }

            }

            弊端: 在多线程并发操作的时候, 有可能创建出多个对象.

        --------------------------------------------------

            class Single2 {

                private Single2() {
                }

                private static Single2 s;

                public static Single2 getInstance() {
                    synchronized (Single2.class) {
                        if (s == null) {
                            s = new Single2();
                        }
                    }
                    return s;
                }

            }

            弊端: 效率非常低

        --------------------------------------------------
     */
    public static void main(String[] args) {
        for (int i = 1; i <= 10; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Single2 s = Single2.getInstance();
                    System.out.println(s);
                }
            }).start();
        }
    }
}

class Single2 {

    private Single2() {
    }

    private static Single2 s;

    public static Single2 getInstance() {
        // 线程2
        // 线程1
        // 此处第一个 if (s == null) 用于提高效率, 避免线程多次重复阻塞, 影响效率
        if (s == null) {
            synchronized (Single2.class) {
                // 第二个 if (s == null) 避免产生不同的线程
                if (s == null) {
                    s = new Single2();
                }
            }
        }

        return s;
    }

}

上一篇:The_Maya_Society-主要分析


下一篇:【Linux】提升Linux命令行效率:光标移动和文本操作的键盘快捷键