如何让线程操作同一个列表Java
How to let threads manipulate the same list Java
我有一个 class,我在其中定义了一个带有添加和删除方法的列表,如下所示:
public class listClass{
private List<T> someList = new ArrayList<>();
public void add(){
//adds to list
}
public void delete(){
//deletes from list
}
}
我还有另一个 class,我在其中定义了两个线程和一个对象,从中我可以访问我的列表。一个线程应使用 add 方法连续添加到列表中,另一个线程应使用 delete 方法从列表中连续删除相应的线程编号:
public class threadClass extends Thread{
private int threadNumber;
public ThreadClass(int threadNumber){
this.threadNumber = threadNumber;
}
listClass listClassObject = new listClass();
public void run(){
if(threadNumber == 1){
while(true){/*add*/}
}
else if(threadNumber ==2){
while(true){/*delete*/}
}
}
}
我怎样才能让两个线程都处理同一个列表?
我当前的实现有一个不同的 class,它有一个 main 方法,我在这里调用线程:
public static void main(String[] args){
threadClass threadForAddingMediaFiles = new threadClass(1);
threadClass threadForDeletionMediaFiles = new threadClass(2);
threadForAddingMediaFiles.start();
threadForDeletionMediaFiles.start();
当前实现的问题是每个线程都创建自己的列表实例(我很清楚,因为列表在同一个 class 中)所以每个线程都操作自己的列表而不是一个通用列表。
在现代 Java 中,我们很少直接称呼 Thread
class。相反,使用添加到 Java 5 中的执行器框架。许多现有的问题和答案中都涵盖了这一点,因此请搜索以了解更多信息。
将您的任务定义为 Runnable
而不是 Thread
。
至于跨线程共享您的列表管理器,请举一个例子。确保您的列表管理员是 thread-safe。您当前的实施不是 thread-safe。一种解决方案是将添加和删除方法都标记为 synchronized
.
将列表管理器对象的一个实例传递给 Runnable
任务对象的构造函数。每个 Runnable
都保留对该列表管理器的引用作为私有成员字段。然后,您所有的可运行对象共享同一个列表管理器。
将所有 Runnable
对象提交给 ExecutorService
。
同样,所有这一切都已经讲过很多次了。搜索以了解更多信息。
我认为发生这种情况是因为您在每个 threadClass 对象中实例化了一个新的 listClass,因此当您修改列表时,您实际上是在每个线程中修改它们自己的“本地”副本。
尝试在您的主函数中实例化该列表,然后将其传递给您的线程,这样您将拥有一个由您的两个线程操作的列表实例 class。
public static void main(String[] args){
listClass myList = new listClass();
threadClass threadForAddingMediaFiles = new threadClass(1, myList);
threadClass threadForDeletionMediaFiles = new threadClass(2, myList);
threadForAddingMediaFiles.start();
threadForDeletionMediaFiles.start();
然后修改你的线程实现:
public class threadClass extends Thread{
private int threadNumber;
private listClass listToHandle;
public ThreadClass(int threadNumber, listClass listToHandle){
this.threadNumber = threadNumber;
this.listToHandle = listToHandle;
}
public void run(){
if(threadNumber == 1){
while(true){/*add*/}
}
else if(threadNumber ==2){
while(true){/*delete*/}
}
}
}
最后记得把你的添加和删除方法放在你的列表中class同步,否则你会遇到一些关于并发访问的问题。
public class listClass{
private List<T> someList = new ArrayList<>();
public synchronized void add(){
//adds to list
}
public synchronized void delete(){
//deletes from list
}
}
您还可以查看 CopyOnWriteArrayList,它是 ArrayList 的 thread-safe 实现。但是,如文档中所述,这通常是一个昂贵的实现,可能不是解决您问题的合适方法。
你可以使用 Collections.synchronizedList() 然后不需要添加同步到 add/delete 方法。创建 ListClass 的实例,然后将其传递给 2 个线程的两个构造函数。
class listClass
{
private List<T> someList = Collections.synchronizedList(new ArrayList<>());
}
我有一个 class,我在其中定义了一个带有添加和删除方法的列表,如下所示:
public class listClass{
private List<T> someList = new ArrayList<>();
public void add(){
//adds to list
}
public void delete(){
//deletes from list
}
}
我还有另一个 class,我在其中定义了两个线程和一个对象,从中我可以访问我的列表。一个线程应使用 add 方法连续添加到列表中,另一个线程应使用 delete 方法从列表中连续删除相应的线程编号:
public class threadClass extends Thread{
private int threadNumber;
public ThreadClass(int threadNumber){
this.threadNumber = threadNumber;
}
listClass listClassObject = new listClass();
public void run(){
if(threadNumber == 1){
while(true){/*add*/}
}
else if(threadNumber ==2){
while(true){/*delete*/}
}
}
}
我怎样才能让两个线程都处理同一个列表?
我当前的实现有一个不同的 class,它有一个 main 方法,我在这里调用线程:
public static void main(String[] args){
threadClass threadForAddingMediaFiles = new threadClass(1);
threadClass threadForDeletionMediaFiles = new threadClass(2);
threadForAddingMediaFiles.start();
threadForDeletionMediaFiles.start();
当前实现的问题是每个线程都创建自己的列表实例(我很清楚,因为列表在同一个 class 中)所以每个线程都操作自己的列表而不是一个通用列表。
在现代 Java 中,我们很少直接称呼 Thread
class。相反,使用添加到 Java 5 中的执行器框架。许多现有的问题和答案中都涵盖了这一点,因此请搜索以了解更多信息。
将您的任务定义为 Runnable
而不是 Thread
。
至于跨线程共享您的列表管理器,请举一个例子。确保您的列表管理员是 thread-safe。您当前的实施不是 thread-safe。一种解决方案是将添加和删除方法都标记为 synchronized
.
将列表管理器对象的一个实例传递给 Runnable
任务对象的构造函数。每个 Runnable
都保留对该列表管理器的引用作为私有成员字段。然后,您所有的可运行对象共享同一个列表管理器。
将所有 Runnable
对象提交给 ExecutorService
。
同样,所有这一切都已经讲过很多次了。搜索以了解更多信息。
我认为发生这种情况是因为您在每个 threadClass 对象中实例化了一个新的 listClass,因此当您修改列表时,您实际上是在每个线程中修改它们自己的“本地”副本。 尝试在您的主函数中实例化该列表,然后将其传递给您的线程,这样您将拥有一个由您的两个线程操作的列表实例 class。
public static void main(String[] args){
listClass myList = new listClass();
threadClass threadForAddingMediaFiles = new threadClass(1, myList);
threadClass threadForDeletionMediaFiles = new threadClass(2, myList);
threadForAddingMediaFiles.start();
threadForDeletionMediaFiles.start();
然后修改你的线程实现:
public class threadClass extends Thread{
private int threadNumber;
private listClass listToHandle;
public ThreadClass(int threadNumber, listClass listToHandle){
this.threadNumber = threadNumber;
this.listToHandle = listToHandle;
}
public void run(){
if(threadNumber == 1){
while(true){/*add*/}
}
else if(threadNumber ==2){
while(true){/*delete*/}
}
}
}
最后记得把你的添加和删除方法放在你的列表中class同步,否则你会遇到一些关于并发访问的问题。
public class listClass{
private List<T> someList = new ArrayList<>();
public synchronized void add(){
//adds to list
}
public synchronized void delete(){
//deletes from list
}
}
您还可以查看 CopyOnWriteArrayList,它是 ArrayList 的 thread-safe 实现。但是,如文档中所述,这通常是一个昂贵的实现,可能不是解决您问题的合适方法。
你可以使用 Collections.synchronizedList() 然后不需要添加同步到 add/delete 方法。创建 ListClass 的实例,然后将其传递给 2 个线程的两个构造函数。
class listClass
{
private List<T> someList = Collections.synchronizedList(new ArrayList<>());
}