Java 如何避免在循环中使用 Thread.sleep()

标签 java producer-consumer

从我的主要开始,我开始了两个名为生产者和消费者的线程。两者都包含 while(true)环形。生产者循环是 UDP 服务器,因此它不需要 sleep 。我的问题出在消费者循环中。消费者循环从链接队​​列中删除对象并将其传递给函数以进行进一步处理。根据研究,在循环中使用线程 sleep 不是一个好习惯,因为有时 O/S 不会在设置时间结束时释放。如果我在应用程序理想时删除线程 sleep ,它会将 CPU 拖到 20% 到 30%。

class Producer implements Runnable {
    private DatagramSocket dsocket;
    FError fer = new FError();

    int port =1548;
    ConcurrentLinkedQueue<String> queue;

    Producer(ConcurrentLinkedQueue<String> queue){
        this.queue = queue; 
    }

    @Override
    public void run() {

        try {

            // Create a socket to listen on the port.
            dsocket = new DatagramSocket(port);
            // Create a buffer to read datagrams into.
            byte[] buffer = new byte[30000];
            // Create a packet to receive data into the buffer
            DatagramPacket packet = new DatagramPacket(buffer,
            buffer.length);

            while (true) {
                try {

                   // Wait to receive a datagram
                    dsocket.receive(packet);
                    //Convert the contents to a string,
                    String msg = new String(buffer, 0, packet.getLength());

                    int ltr = msg.length();
                     // System.out.println("MSG =" + msg);

                    if(ltr>4)
                    {

                        SimpleDateFormat sdfDate = new SimpleDateFormat  ("yyyy-MM-dd HH:mm:ss");//dd/MM/yyyy

                        Date now = new Date();
                        String strDate = sdfDate.format(now);

                        //System.out.println(strDate);

                        queue.add(msg + "&" + strDate);

                     // System.out.println("MSG =" + msg);
                    }

                  // Reset the length of the packet before reusing it.
                   packet.setLength(buffer.length);

                } catch (IOException e) {
                    fer.felog("svr class", "producer", "producer thread",e.getClass().getName() + ": " + e.getMessage());
                    dsocket.close();
                    break; 
                }
            }

        } catch (SocketException e) {
          fer.felog("svr class", "producer","Another App using the udp port " + port, e.getClass().getName() + ": " + e.getMessage()); 

        }

    }

}
class Consumer implements Runnable {

    String str;  
    ConcurrentLinkedQueue<String> queue;

    Consumer(ConcurrentLinkedQueue<String> queue) {
        this.queue = queue;  
    }

    @Override
    public void run() {

        while (true) {
            try {

                while ((str = queue.poll()) != null) {

                    call(str);  // do further processing

                   }
            } catch (IOException e) {
                ferpt.felog("svr class", "consumer", "consumer thread", e.getClass().getName() + ": " + e.getMessage());
                break;
            }

            try {
                Thread.sleep(500);
            } catch (InterruptedException ex) {

                ferpt.felog("svr class", "consumer","sleep", ex.getClass().getName() + ": " + ex.getMessage());
            }

        }

    }

}

最佳答案

而不是让消费者extend Runnable您可以更改您的代码以包含 ScheduledExecutorService它每半秒运行一次队列轮询,而不是让线程 hibernate 。这方面的一个例子是

public void schedule() {
    ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
    executor.scheduleAtFixedRate(() -> {
        String str;
        try {
            while ((str = queue.poll()) != null) {
                call(str);  // do further processing
            }
        } catch (IOException e) {
            ferpt.felog("svr class", "consumer", "consumer thread", e.getClass().getName() + ": " + e.getMessage());
        }
    }, 0, 500, TimeUnit.MILLISECONDS);
}

关于Java 如何避免在循环中使用 Thread.sleep(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54394042/

相关文章:

java - 这里怎么分析时间复杂度呢?

java - Jersey 资源类的托管 Bean

java - 使用重入锁的生产者消费者不起作用

go - 永久 channel 终止程序并与 RabbitMQ 消费者一起进入 channel

java - kafka 消费者可以在从主题中轮询所有消息之前过滤消息吗?

java - 在 Apache Kafka 中设置多个分区

java - 无法通过蓝牙设备地址在android中创建套接字

java - 为什么日志消息不能\n 在文本文件中?

java - 使用数组排序

java - 使用 Java RealTime 的生产者-消费者架构