说我有一个LinkedList填充的对象,每个对象存储我需要的相关信息。我有线程访问此列表的第一个元素以检索信息并对其进行一些操作,在操作结束时,我希望将第一个元素从列表中删除。如何确保为每个元素仅调用一次remove()?这样每个线程都可以访问列表中的下一个相同元素?
public class Test {
private static LinkedList<foo> list;
public static void main(String args[]) {
list = new LinkedList<>();
list.add(foo1);
list.add(foo2);
list.add(foo3);
for(int i = 0; i < 5; i++) {
new Thread(run()).start();
}
}
private static Runnable run() {
while(true) {
while(SomeCondition) {
//Do work.
}
list.remove();
}
}
}
我尝试为remove方法创建一个锁,但这在所有线程的每个元素之间造成了很大的滞后。拥有一个
是个好主意吗?LinkedList<LinkedList<food>> mainList;
,以便每个线程都有自己的工作清单?然后,每个线程都可以执行此操作以访问其元素:
mainList.get(i).element();
mainList.get(i).remove();
编辑: 我没有提到main()有它自己的线程,在该线程中它不断向列表中添加更多元素。主要目的是这是一个不断接收请求的服务器,这些请求作为“队列”放置在列表中。然后从main()分离出来的其他线程执行操作。该请求的消息包含一个字段,该字段将使我知道哪个线程将执行什么操作。
编辑2: 我可能对获得正确答案的要求过于含糊,对不起!这是一台不断接收来自一个客户端的请求的服务器,该列表不断填充请求,为此目的,最重要的字段是请求时间:
for(int i = 0; i < 5; i++) {
new Thread(run(i)).start();
}
private static Runnable run(int streamNumber) {
while(true) {
while(SomeCondition) {
//Do work.
}
list.remove();
}
}
因此,streamNumber规定以下内容: 1.我要广播到的IP地址。 2.使用请求的时间和streamNumber,我需要使用指向有效负载的指针(来自文件)。
最后,每个线程都会将有效载荷发送出去。因此,每个线程需要相同的信息,但响应会有所不同。发送有效负载后,它将抢占下一个请求的时间,并再次进行所有操作。
答案 0 :(得分:1)
首先,当多个线程正在访问列表进行写操作时,LinkedList
简直是一个糟糕的选择。您可以开始here来查找List接口的 other 实现,这些实现更适合此类需求。
正如您自己评论:另一个选择是将数据切片到单独的存储桶中,并将每个线程分配给不同的存储桶。哪种解决方案可以为您带来更好的结果,取决于您的确切要求。创建存储桶具有前期成本,而每次添加/删除元素时,线程安全队列都会使您付出成本。
另一种方法:
该服务之前已实例化,您可以基于ThreadPool或任何其他所需的东西(甚至是单个线程执行器,这对于单元测试也非常有用)。这样就增加了一些开销,因为您必须创建这些任务对象,但这会使其他一切都变得更加简单。
答案 1 :(得分:0)
我采用的解决方案是创建一个:
ExecutorService threadPool = Executors.newFixedThreadPool(5);
while(true) {
Request msg = new Request();
//Set data into msg via DataInputStream
for(int i = 0; i < 5; i++) {
threadPool.execute(stream(i, msg));
}
}
private Runnable stream(int streamNumber, Request msg) {
//Do some work.
}
我没有让5个线程使用1个列表并遇到麻烦,而是将5个任务推入了池中。 streamNumber和message(标志等)将指示在给定的请求时间内任务发生了什么。感谢大家的投入!