Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 线程中的阻塞方法_Java_Multithreading - Fatal编程技术网

Java 线程中的阻塞方法

Java 线程中的阻塞方法,java,multithreading,Java,Multithreading,我想为国际象棋比赛设计一个计时器。 应该有这样一个函数 等待用户输入,然后从控制台移动 如果等待时间>60 停止等待,继续前进 我能想到的解决方法是使用线程: public class Game { Thread t1 = new PlayDisc(this); Thread t2 = new Timer(this); public static void main(String[] args) { t1.start(); t2.start(); } } p

我想为国际象棋比赛设计一个计时器。 应该有这样一个函数

等待用户输入,然后从控制台移动

如果等待时间>60

停止等待,继续前进

我能想到的解决方法是使用线程:

public class Game {
  Thread t1 = new PlayDisc(this);
  Thread t2 = new Timer(this);

  public static void main(String[] args) {
    t1.start();
    t2.start();
  }
}


public class Timer extends Thread{
   Game g;


  public Timer(Game g) {
    this.g = g;
  }

@Override
  public void run() {
    int i = 0;
    while(true){
      if(i > 6000) {
        g.t1.interrupt();
        break;
      }
    }
  }
}

public class PlayDisc extends Thread{
  private Game g;

  public PlayDisc(Game g) {
    this.g = g;
  }

  @Override
  public void run() {
    Scanner s = new Scanner(System.in);

    int x = s.nextInt();
    int y = s.nextInt();

    Point p = new Point(x, y);
    cm.nextPoint = p;
    s.close();
  }


}
我知道这不能作为Scanner使用。nextInt()是一种阻塞方法。但我需要从命令行读取输入。
有什么办法解决这个问题吗

已经有一个
Timer
类(实际上有两个,
java.util.Timer
javax.swing.Timer
)。但正如您所意识到的,
nextInt()
的阻塞特性阻止您在超时后执行任何操作。您将需要一个额外的库,它将为您提供比默认情况下Java更好的控制台控制。或者使用
Swing

编辑:通过使用带有
hasNextInt()
的轮询循环,可以执行某种类型的黑客攻击。这样就不会让扫描线程阻塞


重新编辑:不,这是不可能的,因为hasNext()将被阻止。您必须测试中断是否能帮您摆脱这里的麻烦(可能不会)。

已经有了
计时器类(实际上有两个,
java.util.Timer
javax.swing.Timer
)。但正如您所意识到的,
nextInt()
的阻塞特性阻止您在超时后执行任何操作。您将需要一个额外的库,它将为您提供比默认情况下Java更好的控制台控制。或者使用
Swing

编辑:通过使用带有
hasNextInt()
的轮询循环,可以执行某种类型的黑客攻击。这样就不会让扫描线程阻塞


重新编辑:不,这是不可能的,因为hasNext()将被阻止。您必须测试中断是否能让您摆脱这里的麻烦(可能不会)。

扫描仪的问题是您无法控制方法读取更多字节,这可能会导致阻塞。安全的方法是从
系统中手动读取。在
中,创建一个
扫描仪
,它只能读取您已经从控制台获得的字节。然后,您可以进行轮询(使用睡眠)来实现超时。通过选择适当的睡眠时间,您可以在响应能力和CPU使用率之间获得适当的平衡

下面的示例程序使用200ms的检查间隔,这足以被人类用户视为“即时响应”。此值独立于您可以自由配置的等待时间(只要它明显高于检查间隔)

需要注意的其他事项是,我们在开始时计算截止时间,而不是将等待时间相加,以独立于循环中的CPU使用情况。我们使用
System.nanoTime()
独立于系统时钟可能发生的变化

long timeOutNS=TimeUnit.MINUTES.toNanos(1); // 1 min timeout
long checkNS=TimeUnit.MILLISECONDS.toNanos(200); // check input every 200ms

int input=0;
boolean hasInput=false;

readWithTimeOut: {
  System.out.println("Enter int: ");
  long deadLine=System.nanoTime() + timeOutNS;
  for(;;) {
    int a = System.in.available();
    if(a>0) {
      byte[] b=new byte[a];
      a=System.in.read(b);
      if(a<=0) break readWithTimeOut;
      Scanner scanner=new Scanner(new ByteArrayInputStream(b, 0, a));
      if(scanner.hasNextInt()) {
        input=scanner.nextInt();
        hasInput=true;
        break;
      }
      else if(scanner.hasNext())
        System.err.println("not an int: "+scanner.next()); // consumes token
      continue;
    }
    long remaining=deadLine-System.nanoTime();
    if(remaining<=0) {
      System.err.println("timeout");
      break readWithTimeOut;
    }
    LockSupport.parkNanos(Math.min(remaining, checkNS));
  }
}

System.out.println( hasInput? "entered "+input: "no valid input" ); 
long timeOutNS=TimeUnit.MINUTES.toNanos(1);//1分钟超时
long checkNS=时间单位。毫秒。toNanos(200);//每200ms检查一次输入
int输入=0;
布尔输入=假;
readWithTimeOut:{
System.out.println(“输入int:”);
长截止日期=System.nanoTime()+超时;
对于(;;){
int a=系统中的可用();
如果(a>0){
字节[]b=新字节[a];
a=系统英寸读数(b);

如果(aScanner
的问题是您无法控制该方法读取更多字节,这通常会导致阻塞。安全的方法是从
系统中手动读取。在
中,创建一个
Scanner
,它只能读取您从控制台获得的字节。然后您可以进行轮询(使用睡眠)通过选择适当的睡眠时间,您可以在响应能力和CPU使用率之间获得适当的平衡

下面的示例程序使用200ms的检查间隔,这足以让用户感觉到“即时响应”。该值独立于您可以自由配置的等待时间(只要它明显高于检查间隔)

其他需要注意的是,我们在开始时计算截止时间,而不是将等待时间相加,以独立于循环中的CPU使用情况。我们使用
System.nanoTime()
独立于系统时钟可能发生的变化

long timeOutNS=TimeUnit.MINUTES.toNanos(1); // 1 min timeout
long checkNS=TimeUnit.MILLISECONDS.toNanos(200); // check input every 200ms

int input=0;
boolean hasInput=false;

readWithTimeOut: {
  System.out.println("Enter int: ");
  long deadLine=System.nanoTime() + timeOutNS;
  for(;;) {
    int a = System.in.available();
    if(a>0) {
      byte[] b=new byte[a];
      a=System.in.read(b);
      if(a<=0) break readWithTimeOut;
      Scanner scanner=new Scanner(new ByteArrayInputStream(b, 0, a));
      if(scanner.hasNextInt()) {
        input=scanner.nextInt();
        hasInput=true;
        break;
      }
      else if(scanner.hasNext())
        System.err.println("not an int: "+scanner.next()); // consumes token
      continue;
    }
    long remaining=deadLine-System.nanoTime();
    if(remaining<=0) {
      System.err.println("timeout");
      break readWithTimeOut;
    }
    LockSupport.parkNanos(Math.min(remaining, checkNS));
  }
}

System.out.println( hasInput? "entered "+input: "no valid input" ); 
long timeOutNS=TimeUnit.MINUTES.toNanos(1);//1分钟超时
long checkNS=时间单位。毫秒。toNanos(200);//每200ms检查一次输入
int输入=0;
布尔输入=假;
readWithTimeOut:{
System.out.println(“输入int:”);
长截止日期=System.nanoTime()+超时;
对于(;;){
int a=系统中的可用();
如果(a>0){
字节[]b=新字节[a];
a=系统英寸读数(b);

if(a
InputStream.available()
是一种非阻塞方法,可用于检查流中是否有内容。 如果您不关心旋转(从而浪费处理器内核),那么这就很简单了:

import java.io.IOException;
import java.util.Scanner;

public class ConsoleReadWithTimeout {

    static Scanner scanner = new Scanner(System.in);

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

        int i = readIntWithTimeout(5 * 1000);

        scanner.close();
    }
    // returns -1 in case of timeout
    static private int readIntWithTimeout(long timeoutInMs) throws IOException {
        long startTime = System.currentTimeMillis();
        while (System.in.available() == 0) {
            if (timeoutInMs < System.currentTimeMillis() - startTime) {
                return -1; // or maybe throw a TimeoutException ?
            }
        }
        return scanner.nextInt();
    }
}
import java.io.IOException;
导入java.util.Scanner;
公共类ConsoleReadWithTimeout{
静态扫描仪=新扫描仪(System.in);
公共静态void main(字符串[]args)引发异常{
int i=带超时的readIntWithTimeout(5*1000);
scanner.close();
}
//超时时返回-1
静态私有int readIntWithTimeout(长时间超时)引发IOException{
long startTime=System.currentTimeMillis();
while(System.in.available()==0){
if(timeoutims
InputStream.available()
是一种非阻塞方法,可用于检查流中是否有内容。 如果你不在乎旋转(和t