Java 采用ReentrantLock和Synchronized实现多线程案例(哲学家就餐问题、多个线程交替打印、抢票案例)


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



public class ThreadCaseTest {

    static ReentrantLock lock = new ReentrantLock();

    static final Object o = new Object(); //共享变量

    static volatile int num = 0; //volatile 多线程情况下保证数据的可见性

    static final int ticketNums = 100; //总票数

    static final int peopleSize = 200; //抢票人数

    static int ticketNum;//票数

    static int peopleNum;//人数

    static String code = "A"; //默认是A

    public static void main(String[] args) throws Exception {

        demo1();
        demo2();
        demo3();
        demo4();
        demo5();
        demo6();
        demo7();
        demo8();

    }

    /**
     * 8. 两个线程交替打印奇偶数。0-100
     */
    private static void demo8() {

        Condition a = lock.newCondition();
        Condition b = lock.newCondition();

        new Thread(() -> {
            while (num < 100) {
                try {
                    lock.lock();
                    if (num % 2 == 1) {
                        a.await();//当前线程等待
                    }
                    System.out.println(Thread.currentThread().getName() + num);
                    num++;
                    b.signal();//唤醒另一个线程
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();//释放锁
                }
            }
        }, "线程A: ").start();

        new Thread(() -> {
            while (num < 100) {
                try {
                    lock.lock();
                    if (num % 2 == 0) {
                        b.await();
                    }
                    System.out.println(Thread.currentThread().getName() + num);
                    num++;
                    a.signal();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }, "线程B: ").start();
    }

    /**
     * 7. 抢票案例
     */
    private static void demo7() {

        new TicketThread("窗口A").start();

        new TicketThread("窗口B").start();

        new TicketThread("窗口C").start();

        new TicketThread("窗口D").start();

    }

    /**
     * 6. 哲学家就餐问题
     */
    private static void demo6() {
        Chopsticks chopsticks0 = new Chopsticks();
        Chopsticks chopsticks1 = new Chopsticks();
        Chopsticks chopsticks2 = new Chopsticks();
        Chopsticks chopsticks3 = new Chopsticks();
        Chopsticks chopsticks4 = new Chopsticks();

        new Philosohper("哲学家1", 1, chopsticks0, chopsticks1).start();
        new Philosohper("哲学家2", 2, chopsticks1, chopsticks2).start();
        new Philosohper("哲学家3", 3, chopsticks2, chopsticks3).start();
        new Philosohper("哲学家4", 4, chopsticks3, chopsticks4).start();
        new Philosohper("哲学家5", 5, chopsticks4, chopsticks0).start();

    }

    /**
     * 5. 三个线程 a、b、c 并发运行,b,c 需要 a 线程的数据怎么实现
     */
    private static void demo5() {
        new Thread(() -> {
            try {
                //模拟耗时操作之后初始化变量 num
                Thread.sleep(1000);
                num = 1;
                System.out.println(Thread.currentThread().getName() + "获取到 num 的值为:" + num);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "线程A:").start();

        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "获取到 num 的值为:" + num);
        }, "线程B:").start();

        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "获取到 num 的值为:" + num);
        }, "线程C:").start();
    }

    /**
     * 4. 三个线程的Name分别是A,B,C;每个线程将自己的Name在控制台上打印5遍,打印顺序是ABC ABC...
     */
    private static void demo4() {

        Condition a = lock.newCondition();
        Condition b = lock.newCondition();
        Condition c = lock.newCondition();

        printA(a, b);

        printB(b, c);

        printC(c, a);

    }

    /**
     * 3. 写两个线程,一个线程打印1~ 52,另一个线程打印A~Z,打印顺序是12A34B...5152Z
     * 字母个数:26 A~Z。大写字母的A是65开始的,对应ASCII码表
     */
    private static void demo3() {

        new Thread(() -> {
            synchronized (o) {
                try {
                    while (num < 52) {
                        num++;
                        System.out.println(Thread.currentThread().getName() + num);
                        if (num % 2 == 0) {
                            o.notify();
                            o.wait();
                        }
                    }
                    o.notify();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, "线程A:").start();

        new Thread(() -> {
            synchronized (o) {
                try {
                    for (int i = 0; i < 26; i++) {
                        System.out.println(Thread.currentThread().getName() + (char) (65 + i));
                        o.notify();
                        o.wait();
                    }
                    o.notify();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, "线程B:").start();
    }

    /**
     * 2. 两个线程轮流打印数字,一直到100。t1:1,t2:2;t1:3,t2:4;......
     */
    private static void demo2() {

        new Thread(() -> {
            synchronized (o) {
                while (num < 100) {
                    try {
                        num++;
                        System.out.println(Thread.currentThread().getName() + num);
                        o.notify();
                        o.wait();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                o.notify();
            }
        }, "线程A: ").start();

        new Thread(() -> {
            synchronized (o) {
                while (num < 100) {
                    try {
                        num++;
                        System.out.println(Thread.currentThread().getName() + num);
                        o.notify();
                        o.wait();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                o.notify();
            }
        }, "线程B: ").start();
    }

    /**
     * 1. 要求线程a执行完才开始线程b, 线程b执行完才开始线程c
     *
     * @throws Exception
     */
    private static void demo1() throws Exception {

        PrintThread threadA = new PrintThread("A");
        PrintThread threadB = new PrintThread("B");
        PrintThread threadC = new PrintThread("C");

        threadA.start();
        threadA.join();

        threadB.start();
        threadB.join();

        threadC.start();
        threadC.join();
    }

    static class PrintThread extends Thread {

        PrintThread(String name) {
            super(name);
        }

        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                System.out.println(Thread.currentThread().getName() + ": " + i);
            }
        }
    }

    private static void printA(Condition a, Condition b) {
        new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                lock.lock();
                try {
                    if (!code.equalsIgnoreCase("A")) a.await();
                    System.out.println(Thread.currentThread().getName() + i);
                    code = "B";
                    b.signal();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }, "线程A:").start();
    }

    private static void printB(Condition b, Condition c) {
        new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                lock.lock();
                try {
                    if (!code.equalsIgnoreCase("B")) b.await();
                    System.out.println(Thread.currentThread().getName() + i);
                    code = "C";
                    c.signal();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }, "线程B:").start();
    }

    private static void printC(Condition c, Condition a) {
        new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                lock.lock();
                try {
                    if (!code.equalsIgnoreCase("C")) c.await();
                    System.out.println(Thread.currentThread().getName() + i);
                    code = "A";
                    a.signal();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }, "线程C:").start();
    }

    static class Philosohper extends Thread {

        private String name;//名字
        private int num;//编号
        private Chopsticks left, right;//筷子

        Philosohper(String name, int num, Chopsticks left, Chopsticks right) {
            this.name = name;
            this.num = num;
            this.left = left;
            this.right = right;
        }

        @Override
        public void run() {
            if (num % 2 == 0) { //假设有人是左撇子
                synchronized (left) {
                    try {
                        sleep(1000);
                        synchronized (right) {
                            System.out.println("编号为:" + num + " 名字为:" + name + " 开始吃饭了");
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            } else {
                synchronized (right) {
                    try {
                        sleep(1000);
                        synchronized (left) {
                            System.out.println("编号为:" + num + " 名字为:" + name + " 开始吃饭了");
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }

        }
    }

    static class Chopsticks {

    }

    static class TicketThread extends Thread {

        private String windowName;

        TicketThread(String windowName) {
            this.windowName = windowName;
        }

        @Override
        public void run() {
            synchronized (o) {
                while (ticketNum < ticketNums && peopleNum < peopleSize) {
                    if (peopleNum % 2 == 1) {
                        System.out.println(windowName + " " + Thread.currentThread().getName() + " 第" + (++peopleNum) + "个人抢到第" + (++ticketNum) + " 张票");
                        try {
                            Thread.sleep(100);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    } else {
                        System.out.println(windowName + " " + Thread.currentThread().getName() + " 第" + (++peopleNum) + " 个人未抢到票");
                    }
                }
            }
        }

    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值