如何让线程根据 Scanner 提供的条件执行操作?

How can I get threads to do action based on condition provided by Scanner?

非常感谢您查看我的问题,我对一个可能有简单解决方案的问题感到非常困惑和沮丧,非常感谢任何帮助。

我想要的是有两个关闭或打开的 Barrier 实例,我想确定屏障是否应该打开的方式是通过扫描仪,所以如果我单击 1,我应该得到消息 "Entrance Barrier " + threadid + “已打开”

  public class MainClass{
    public static void main(String[] args) {

      EntranceBarrier e1 = new EntranceBarrier(); //Entrance Barrier 1
      EntranceBarrier e2 = new EntranceBarrier(); //Entrance Barrier 2

        e1.start();
        e2.start();

        System.out.println("Open?");
        Scanner sc = new Scanner(System.in);
        int operation = sc.nextInt();


       while(operation != 0){

          switch (operation) {
              case 1:
                  e1.setOpen(true);
                  e2.setOpen(true);
                  System.out.println("Opt. 1 Working");
                  break;
              case 2:
                  e1.setOpen(false);
                  e2.setOpen(false);
                  System.out.println("Opt. 2 Working");
                  break;
              default:
                  System.out.println("NOPE");
                  break;
          }

         System.out.println("Open?");
         operation = sc.nextInt();
       }


    }
   }

每当我 运行 main 方法时,它首先打印出 "Entrance Barrier Closed",当我向扫描仪输入 1 时,它只打印出 "Opt. 1 Working",这意味着它没有改变 setOpen()为真。

这是 EntranceBarrier class:

import java.io.*;
import java.util.Scanner;

public class EntranceBarrier extends Thread {

    private volatile boolean open = false;

    public synchronized void OpenBarrier(){
     if(isOpen()){
        try{
          String threadid = Thread.currentThread().getName();
          System.out.println("Entrance Barrier " + threadid + " Opened");
          Thread.sleep(5000);
        }catch(InterruptedException e){
           e.printStackTrace();
        }
       } else{
          System.out.println("Entrance Barrier Closed");

       }

    }

    public void run() {
       OpenBarrier();
    }

    public boolean isOpen() {
        return open;
    }

    public void setOpen(boolean open) {
        this.open = open;
    }

}

不知道这个问题问的够不够清楚,真心希望大家能帮帮我,快撕逼我了D:

我想提出一些修改建议。

首先我想命名所有入口线程:

import java.util.Scanner;

public class MainClass {
public static void main(String[] args) {

    EntranceBarrier e1 = new EntranceBarrier(); // Entrance Barrier 1
    e1.setName("Bar1");
    EntranceBarrier e2 = new EntranceBarrier(); // Entrance Barrier 2
    e2.setName("Bar2");

    e1.start();
    e2.start();

    System.out.println("Open?");
    Scanner sc = new Scanner(System.in);
    int operation = sc.nextInt();

    while (operation != 0) {
        switch (operation) {
        case 1:
            e1.setOpen(true);
            e2.setOpen(true);
            System.out.println("Opt. 1 Working");
            break;
        case 2:
            e1.setOpen(false);
            e2.setOpen(false);
            System.out.println("Opt. 2 Working");
            break;
        default:
            System.out.println("NOPE");
            break;
        }

        System.out.println("Open?");
        operation = sc.nextInt();
    }
}
}

接下来我想添加一个循环来主动检查是否请求更改入口线程的状态以及保存此信息的变量。

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

public class EntranceBarrier extends Thread {

    private volatile boolean open = false;
    private volatile boolean requestedState = false;

    private Lock lock = new ReentrantLock();

    public void OpenBarrier() {
        try {
            lock.lock();
            printState();
            lock.unlock();

            while (true) {
                lock.lock();
                if (requestedState != open) {
                    printState();

                    Thread.sleep(5000);
                    open = requestedState;

                    printState();
                }
                lock.unlock();
                Thread.sleep(100);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
            lock.unlock();
        }
    }

    private void printState() {
        if (requestedState == open) {
            if (open)
                System.out.println("Entrance Barrier " + getName() + " Opened");
            else
                System.out.println("Entrance Barrier " + getName() + " Closed");
        } else {
            if (requestedState)
                System.out.println("Entrance Barrier " + getName() + " Opening");
            else
                System.out.println("Entrance Barrier " + getName() + " Closing");
        }
    }

    public void run() {
        OpenBarrier();
    }

    public boolean isOpen() {
        return open;
    }

    public void setOpen(boolean open) {
        if (lock.tryLock()) {
            this.requestedState = open;
            lock.unlock();
        } else {
            System.out.println("Entrance Barrier " + getName() + " is moving");
        }
    }
}

我使用可重入锁而不是同步关键字来检查锁是否已被锁定。如果正在进行入口状态更改,它会启用 setOpen 函数以退出。

可以使用 wait()/notify() 进一步升级 EntranceBarrier。可以用更高效的方式代替主动等待。

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

public class EntranceBarrier extends Thread {

    private volatile boolean open = false;
    private volatile boolean requestedState = false;

    private Lock lock = new ReentrantLock();

    public void OpenBarrier() {
        try {
            lock.lock();
            printState();
            lock.unlock();

            while (true) {
                // waiting for state change request
                synchronized (this) {
                    wait();
                }
                lock.lock();
                if (requestedState != open) {
                    printState();

                    Thread.sleep(5000);
                    open = requestedState;

                    printState();
                }
                lock.unlock();
                // Thread.sleep(100);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
            lock.unlock();
        }
    }

    private void printState() {
        if (requestedState == open) {
            if (open)
                System.out.println("Entrance Barrier " + getName() + " Opened");
            else
                System.out.println("Entrance Barrier " + getName() + " Closed");
        } else {
            if (requestedState)
                System.out.println("Entrance Barrier " + getName() + " Opening");
            else
                System.out.println("Entrance Barrier " + getName() + " Closing");
        }
    }

    public void run() {
        OpenBarrier();
    }

    public boolean isOpen() {
        return open;
    }

    public void setOpen(boolean open) {
        if (lock.tryLock()) {
            this.requestedState = open;
            // notifying that state change was requested
            synchronized (this) {
                notify();
            }
            lock.unlock();
        } else {
            System.out.println("Entrance Barrier " + getName() + " is moving");
        }
    }
}