如何在Java线程中监听特定时间?

如何在Java线程中监听特定时间?,java,multithreading,Java,Multithreading,我正在创建多个线程,我希望每个线程在其阻止队列中侦听任何新消息2秒钟,然后消失。我正在使用以下代码: public class Main { public static void main(String[] argv) throws Exception { int capacity = 10; BlockingQueue<String> queue = new ArrayBlockingQueue<String>(capacity)

我正在创建多个线程,我希望每个线程在其阻止队列中侦听任何新消息2秒钟,然后消失。我正在使用以下代码:

public class Main {
    public static void main(String[] argv) throws Exception {
        int capacity = 10;
        BlockingQueue<String> queue = new ArrayBlockingQueue<String>(capacity);

        ArrayList<String> names = new ArrayList<String>();
        names.add("Apple"); names.add("Banana"); names.add("Mango");
        HashMap<String, Worker> workermap = new HashMap<String, Worker>();
        for (String name: names) {
            Worker a_worker = new Worker(queue);
            a_worker.setName(name);
            a_worker.start();
            workermap.put(name, new Worker(queue));
        }
        queue.put("Hello ");
    }
}

class Worker extends Thread {
    BlockingQueue<String> q;

    Worker(BlockingQueue<String> q) {
        this.q = q;
    }

    public void run() {
        try {
            long start = System.currentTimeMillis();
            long end = start + 2*1000;
            while (true) {
                String x = q.take();
                if(System.currentTimeMillis()>=end){
                    System.out.println("No new message since two seconds, killing thread " + this.getName());
                    Thread.interrupted();
//                    break;
                }
//                if (x == null) {
//                    break;
//                }

                System.out.println(x + "from " + this.getName());
            }

        } catch (InterruptedException e) {
        }
    }
}

但我只是从苹果公司那里得到了你好,之后就什么也没有了。该过程继续进行,没有任何进一步的输出。除了使用计时器终止线程外,我还尝试检查队列元素是否为null,但没有成功。我哪里出错了?

如前所述,您需要使用pool而不是take(),而且您不能使用
Thread.interrupted()
中断
a
线程
。您需要使用
Thread.currentThread().interrupt()。此外,您不需要检查时间,因为
BlockingQueue#poll
do将等待
2

    while (!Thread.currentThread().isInterrupted()) {
        String x = q.poll(2, TimeUnit.SECONDS);
       if (x == null)
         System.out.println("No new message since two seconds, killing thread " + this.getName());
        Thread.currentThread().interrupt();
        System.out.println(x + "from " + this.getName());
    }
输出:

No new message since two seconds, killing thread Mango
Hello from Mango
No new message since two seconds, killing thread Apple
nullfrom Apple
No new message since two seconds, killing thread Banana
nullfrom Banana
编辑:但是我相信你根本不需要一个循环。下面的代码对您来说很好

public void run() {
    try {
        String x = q.poll(2, TimeUnit.SECONDS);
        if (x == null)
          System.out.println("No new message since two seconds, killing thread " + this.getName());
        System.out.println(x + "from " + this.getName());
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

如前所述,您需要使用pool而不是take(),并且不能使用
Thread.interrupted()
中断
a
线程
。您需要使用
Thread.currentThread().interrupt()。此外,您不需要检查时间,因为
BlockingQueue#poll
do将等待
2

    while (!Thread.currentThread().isInterrupted()) {
        String x = q.poll(2, TimeUnit.SECONDS);
       if (x == null)
         System.out.println("No new message since two seconds, killing thread " + this.getName());
        Thread.currentThread().interrupt();
        System.out.println(x + "from " + this.getName());
    }
输出:

No new message since two seconds, killing thread Mango
Hello from Mango
No new message since two seconds, killing thread Apple
nullfrom Apple
No new message since two seconds, killing thread Banana
nullfrom Banana
编辑:但是我相信你根本不需要一个循环。下面的代码对您来说很好

public void run() {
    try {
        String x = q.poll(2, TimeUnit.SECONDS);
        if (x == null)
          System.out.println("No new message since two seconds, killing thread " + this.getName());
        System.out.println(x + "from " + this.getName());
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

我只是尝试对您的代码进行最小修复:

import java.util.ArrayList;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class Main {
    public static void main(String[] argv) throws Exception {
        int capacity = 10;
        BlockingQueue<String> queue = new ArrayBlockingQueue<String>(capacity);

        ArrayList<String> names = new ArrayList<String>();
        names.add("Apple"); names.add("Banana"); names.add("Mango");
        for (String name: names) {
            Worker a_worker = new Worker(queue);
            a_worker.setName(name);
            a_worker.start();
        }
        queue.put("Hello");
        queue.put("Bonjour");
    }
}

class Worker extends Thread {
    BlockingQueue<String> q;

    Worker(BlockingQueue<String> q) {
        this.q = q;
    }

    public void run() {
        long start = System.currentTimeMillis();
        long end = start + 2; //just wait for two milliseconds

        while (true) {
            String x = q.poll();
            if(x != null) {
                System.out.println(x + " from " + this.getName());
            } else if(System.currentTimeMillis() >= end){
                System.out.println("No new message since two milliseconds, killing thread " + this.getName());
                interrupt();
            }

            if(interrupted()) {
                break;
            }
        }
    }
}

我只是尝试对您的代码进行最小修复:

import java.util.ArrayList;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class Main {
    public static void main(String[] argv) throws Exception {
        int capacity = 10;
        BlockingQueue<String> queue = new ArrayBlockingQueue<String>(capacity);

        ArrayList<String> names = new ArrayList<String>();
        names.add("Apple"); names.add("Banana"); names.add("Mango");
        for (String name: names) {
            Worker a_worker = new Worker(queue);
            a_worker.setName(name);
            a_worker.start();
        }
        queue.put("Hello");
        queue.put("Bonjour");
    }
}

class Worker extends Thread {
    BlockingQueue<String> q;

    Worker(BlockingQueue<String> q) {
        this.q = q;
    }

    public void run() {
        long start = System.currentTimeMillis();
        long end = start + 2; //just wait for two milliseconds

        while (true) {
            String x = q.poll();
            if(x != null) {
                System.out.println(x + " from " + this.getName());
            } else if(System.currentTimeMillis() >= end){
                System.out.println("No new message since two milliseconds, killing thread " + this.getName());
                interrupt();
            }

            if(interrupted()) {
                break;
            }
        }
    }
}

使用
BlockingQueue.poll(2,TimeUnit.SECONDS)
。使用
BlockingQueue.poll(2,TimeUnit.SECONDS)
。谢谢,这解决了两秒后终止线程的问题。但是我想打印所有线程的hello,然后在两秒钟后杀死它们。我们如何做到这一点:启动所有三个线程>从所有三个线程打印hello>让他们监听任何新消息两秒钟>最后杀死所有线程three@smaug在终止队列之前打印
Hello
是什么意思?如果您想向所有3个线程提供消息“Hello”,那么请在队列中再添加两次“Hello”。即使如此,也不能保证在任何一个线程被终止之前打印所有“Hello”消息。@smaug在这种情况下,您需要确保在
工作线程开始之前将消息提供给队列。在您的例子中,put
queue.put(“Hello”)for
循环之前,code>3次。谢谢,这解决了在两秒钟后终止线程的问题。但是我想打印所有线程的hello,然后在两秒钟后杀死它们。我们如何做到这一点:启动所有三个线程>从所有三个线程打印hello>让他们监听任何新消息两秒钟>最后杀死所有线程three@smaug在终止队列之前打印
Hello
是什么意思?如果您想向所有3个线程提供消息“Hello”,那么请在队列中再添加两次“Hello”。即使如此,也不能保证在任何一个线程被终止之前打印所有“Hello”消息。@smaug在这种情况下,您需要确保在
工作线程开始之前将消息提供给队列。在您的例子中,put
queue.put(“Hello”)for
循环之前,code>3次。