模拟交通信号灯(一个盒子)

时间:2020-05-31 21:49:03

标签: java multithreading condition-variable reentrantlock

我想实施一个交通信号灯(一个盒子)。我看到SO中有很多问题,但我觉得它们不是完整的代码。

以下是完整的来源。我正在使用lockcondition来决定实际运行哪个线程。

TrafficSignalSimulationUsingLock.java

package com.example.practice.third;

import java.util.concurrent.locks.Condition;

import com.example.practice.third.custom.lock.TrafficLock;
import com.example.practice.third.threads.GreenColorLightThread;
import com.example.practice.third.threads.RedColorLightThread;
import com.example.practice.third.threads.YellowColorLightThread;

public class TrafficSignalSimulationUsingLock {

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

        TrafficLock lock = new TrafficLock();

        Condition condition = lock.newCondition();

        Thread redThread = new Thread(new RedColorLightThread(lock, condition));
        Thread yellowThread = new Thread(new YellowColorLightThread(lock, condition));
        Thread greenThread = new Thread(new GreenColorLightThread(lock, condition));

        redThread.start();

        Thread.sleep(300);

        yellowThread.start();
        greenThread.start();

        redThread.join();
        yellowThread.join();
        greenThread.join();
    }
}

RedColorLightThread.java

package com.example.practice.third.threads;

import java.util.concurrent.locks.Condition;

import com.example.practice.third.custom.lock.TrafficLock;

public class RedColorLightThread implements Runnable {

    private TrafficLock trafficLock;
    private Condition condition;

    public RedColorLightThread(TrafficLock trafficLock, Condition condition) {
        this.trafficLock = trafficLock;
        this.condition = condition;
    }

    @Override
    public void run() {

        while (true) {
            try {
                trafficLock.lock();

                while (trafficLock.isYellow() && trafficLock.isGreen()) {
                    try {
                        condition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                for (int i = 0; i < 5; i++) {
                    System.out.println("Red signal enabled");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                trafficLock.setYellow(true);
                trafficLock.setGreen(false);
                condition.signalAll();

            } finally {
                trafficLock.unlock();
            }
        }
    }
}

YellowColorLightThread.java

package com.example.practice.third.threads;

import java.util.concurrent.locks.Condition;

import com.example.practice.third.custom.lock.TrafficLock;

public class YellowColorLightThread implements Runnable {

    private TrafficLock trafficLock;
    private Condition condition;

    public YellowColorLightThread(TrafficLock trafficLock, Condition condition) {
        this.trafficLock = trafficLock;
        this.condition = condition;
    }

    @Override
    public void run() {

        while (true) {
            try {
                trafficLock.lock();

                while (trafficLock.isRed() && trafficLock.isGreen()) {
                    try {
                        condition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                for (int i = 0; i < 3; i++) {
                    System.out.println("Yellow signal enabled");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                trafficLock.setRed(false);
                trafficLock.setGreen(true);
                condition.signalAll();

            } finally {
                trafficLock.unlock();
            }
        }
    }
}

GreenColorLightThread.java

package com.example.practice.third.threads;

import java.util.concurrent.locks.Condition;

import com.example.practice.third.custom.lock.TrafficLock;

public class GreenColorLightThread implements Runnable {

    private TrafficLock trafficLock;
    private Condition condition;

    public GreenColorLightThread(TrafficLock trafficLock, Condition condition) {
        this.trafficLock = trafficLock;
        this.condition = condition;
    }

    @Override
    public void run() {

        while (true) {
            try {
                trafficLock.lock();

                while (trafficLock.isRed() && trafficLock.isYellow()) {
                    try {
                        condition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                for (int i = 0; i < 5; i++) {
                    System.out.println("Green signal enabled");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                trafficLock.setRed(true);
                trafficLock.setYellow(false);
                condition.signalAll();

            } finally {
                trafficLock.unlock();
            }
        }
    }
}

TrafficLock.java

package com.example.practice.third.custom.lock;

import java.util.concurrent.locks.ReentrantLock;

public class TrafficLock extends ReentrantLock {

    /**
     * 
     */
    private static final long serialVersionUID = 7311233763066170670L;

    private boolean red = true;
    private boolean yellow = false;
    private boolean green = false;

    public TrafficLock() {
        super(true);
    }

    public boolean isRed() {
        return red;
    }

    public void setRed(boolean red) {
        this.red = red;
    }

    public boolean isYellow() {
        return yellow;
    }

    public void setYellow(boolean yellow) {
        this.yellow = yellow;
    }

    public boolean isGreen() {
        return green;
    }

    public void setGreen(boolean green) {
        this.green = green;
    }
}

以下是示例输出:

Red signal enabled
Red signal enabled
Red signal enabled
Red signal enabled
Red signal enabled
Yellow signal enabled
Yellow signal enabled
Yellow signal enabled
Green signal enabled
Green signal enabled
Green signal enabled
Green signal enabled
Green signal enabled
Red signal enabled
Red signal enabled

这是正确的实现方式吗(请忽略空格,时间复杂度)

尽管此程序可以达到我期望的结果,但我有一个小疑问:

在每个“彩色线程”(例如“ RedColorLightThread”)中,线程首先设置下一个所需的状态,然后设置condition.signalAll(),并在finally block中释放锁。

我的疑问是,例如“红色线程”还没有释放锁时,其他线程是否会立即唤醒?

1 个答案:

答案 0 :(得分:0)

一次只能由一个线程持有锁。当您向其他线程发出信号时,您是在告诉他们它们可以唤醒并尝试获取该锁,但是它们只有在获得该锁时才会继续前进。只有在其他线程将其解锁时才会发生这种情况。之后,只有等待的线程会唤醒并锁定该锁,而其他线程则保持等待。

相关问题