【问题标题】:How to add threads to an ArrayList如何将线程添加到 ArrayList
【发布时间】:2014-08-22 10:06:40
【问题描述】:

我有一个类,SmartQueue,它扩展了 Thread,看起来像这样

public class SmartQueue extends Thread {
    public int idQ;
    public LinkedList<Client> sQueue = new LinkedList<Client>();
    ......
//pops an element from sQueue after a random time in a specified interval
//and then waits to be notified again 

从另一个类 QManager 我想在 for 循环中创建一些 SmartQueue 线程,并通过将它们添加到 ArrayList 来跟踪它们。然后在另一个指定时间间隔的某个随机时间在 SmartQueue.sQueue 中一次添加一个元素。此外,SmartQueue 中元素的删除也将在 QManager 类中触发,方法是...从 ArrayList 中“提取”线程并通知它。

基本上,我正在尝试创建一个队列模拟器,其中生成的“客户端”到达并在/在某个随机时间提供服务,每个队列都有自己的处理器并与其他队列同时作为线程运行

ArrayList 跟踪线程的方式是可行的还是......只是愚蠢的? 我该怎么做?也欢迎任何关于如何实现这个模拟器的想法

【问题讨论】:

  • SmartQueue 是线程吗?真的有理由扩展 Thread 吗?
  • 是 SmartQueue 是一个线程。 SmartQueue 的每个实例都是一个线程,所有实例都应该并发运行
  • @svenoaks 可能想说的是,扩展 Thread 是 20 世纪定义线程入口点的一种方式。 21 世纪的方式是实例化裸线程类,并给它一个 Runnable 委托。 new Thread(new Runnable() { public void run() { ... }}); 长期的好处是它让你养成使用委托而不是使用类型继承的习惯——在编写干净、可重用、可维护的代码的道路上迈出了一步。
  • 是的,我知道使用 Runnable 更好,但是……说实话,我对线程的工作并不多,我发现使用 Runnable 有点困难,但我很快就适应了使用线程,我的意思是它基本上只是继承。我同意,这是有长期利益的,但我没有太多时间,我需要快速完成这项工作,这是大学的评估。这种方式更容易。代码不会以任何主要方式被重用或维护。更有可能会被遗忘。之后我会尝试一些个人项目,并在那里开始使用 Runnable。无论如何,谢谢!

标签: java multithreading arraylist


【解决方案1】:

cmets 中指出的问题不仅仅是表面上的问题。制作Thread 的子类会导致错误的想法,您的问题完美地表明了这一点。

访问变量的线程与持有该变量的对象没有任何关系,即使该对象恰好是Thread 的一个实例。创建Thread 的子类并将实例变量放入其中会导致错误地认为Thread 实例所代表的线程与该实例的变量之间存在关系。

您在询问是否可以将这些实例放入 ArrayList 中,这是一种症状,当然,您可以这样做,因为它们是 Thread 的实例与此处无关。

但是鉴于您对您想要做什么的不完整描述,您似乎至少有一个线程通过QManager 访问sQueue 中的LinkedList&lt;Client&gt;,而另一个线程(恰好是由您的 SmartQueue 实例,但仍然无关紧要)也可以。除非您采取措施实现对LinkedList 的线程安全访问,否则这将中断。所以你把注意力集中在关于线程安全的错误地方只是因为你的SmartQueue 扩展了Thread...

【讨论】:

  • 好的,但是...使用 Runnable 是否允许我将每个线程视为具有自己变量的 SmartQueue 的单独实例?如果没有,我该怎么做?我可以先吗?
  • 线程是 no 的 SmartQueue 实例。绝不。这就是重点,让SmartQueue 成为Thread 的子类会让你认为存在根本不存在的关系。使用Runnable 可以帮助您了解线程只是在执行一个action,即run 方法中的代码,仅此而已。包含的变量是否被一个或多个线程访问取决于您的整个应用程序逻辑。如前所述,您的(模糊)描述表明您想要通过多个线程访问数据。所以你必须让它们线程安全。
  • 是的,好的,我明白了,线程基本上不是对象,它们只是...“做某事”。我想做的是...将每个线程绑定到同一类的某个实例,以便每个线程可以 act 并修改某个实例的变量(在这种情况下为sQueue)一类(SmartQueue)。在循环中按顺序执行此操作非常容易,但我试图同时执行此操作(...至少从软件的角度来看),我有点困惑,我没有真的不知道该怎么做
  • 为每个线程分配一个它应该工作的对象是没有问题的。您只需要将它传递给Runnable,或者您甚至可以让SmartQueue 实现Runnable,这样它的run 方法自然会在正确的对象上工作。但是,将对象分配给工作线程并不会自动阻止其他线程访问同一对象。您必须适当地设计应用程序。据我了解,您希望线程从队列中获取和处理项目,但还有其他人放置这些项目。所以你需要使用线程安全的队列。
【解决方案2】:

这很好。只要 QueueManager 是单线程的,任何 Queue、LinkedList 或 ArrayList 都可以正常工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-30
    • 2020-11-08
    • 1970-01-01
    • 2017-09-19
    • 1970-01-01
    • 1970-01-01
    • 2021-05-26
    相关资源
    最近更新 更多