【问题标题】:creating multiple threads with a unique id (threads do not overlap)创建具有唯一 ID 的多个线程(线程不重叠)
【发布时间】:2021-07-22 21:37:04
【问题描述】:

更新

我正在解决生产者/消费者问题,我想创建一些生产者和消费者(几个线程),我有一个问题,我该如何正确创建多个线程,这样一个任务就不会由两个线程执行(每个线程执行不同的任务)。

代码:我试图在这样的循环中这样做:

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

    public class ProducerConsumerExample {
    
        public static void main(String[] args) {
    
            BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(10);
    
            for (int i = 0; i < 10 ; i++) {
                Producer producer = new Producer(blockingQueue);
                Consumer consumer = new Consumer(blockingQueue);
    
                Thread producerThread = new Thread(producer);
                Thread consumerThread = new Thread(consumer);
    
                producerThread.start();
                consumerThread.start();
            }
        }
    }

输出:但它不起作用,因为线程相互重叠

Producer produced : 1619703940537
Producer produced : 1619703940537
Producer produced : 1619703940537
Producer produced : 1619703940537
consumed gets: 1619703940537
consumed gets: 1619703940537
consumed gets: 1619703940537
consumed gets: 1619703940537
Producer produced : 1619703940537
consumed gets: 1619703940537

【问题讨论】:

标签: java multithreading loops producer-consumer


【解决方案1】:

您正在寻找的是线程池。 Java 中包含各种开箱即用的实现。这是我从javatpoint 中得出的定义:

Java 线程池代表一组等待作业并多次重用的工作线程。在线程池的情况下,会创建一组固定大小的线程。服务提供者从线程池中拉出一个线程并分配一个作业。

您可以查看以下页面了解更多信息:

https://www.baeldung.com/thread-pool-java-and-guava https://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html

【讨论】:

    【解决方案2】:

    您看到多个线程使用相同的 System.currentTimeMillis() 值,这使得无法判断发生了什么。将您传递到队列中的令牌更改为唯一的 PER Producer 并包含线程名称:

    public void run() {
        int counter=0;
        while (true) {
    
            try {
                String token = Thread.currentThread().toString() + "#"+(counter++);
                this.blockingQueue.put(token );
                System.out.println("Producer produced nr: " + token );
            } catch (InterruptedException e ) {
                System.out.println("Producer was interrupted");
            }
            sleep();
        }
    }
    

    更改Consumer.run() 也打印线程名称,您会更清楚地看到哪个消费者实例正在消费每个操作以及来自哪个生产者:

    System.out.println("consumer "+Thread.currentThread()+" gets: " + element);
    

    这将有望证明这些是多个 Producer + Consumer 处理程序以及 Producer-Consumer 从同一个 BlockingQueue 发送和接收项目的不同排列。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-09
      • 2018-03-10
      • 2021-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多