使用Runnable通过多个线程运行方法 [英] Using Runnable to run a method by multiple threads

查看:73
本文介绍了使用Runnable通过多个线程运行方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的程序中,我想在其中一种方法中创建多个线程,其中每个线程必须使用给定的输入运行特定的方法.我使用Runnable编写了此代码段.

In my program, I want to create multiple threads in one of the methods where each thread has to run a specific method with a given input. Using Runnable, I have written this snippet.

class myClass {
  public myClass() { }
  public void doProcess() {
    List< String >[] ls;
    ls = new List[2];  // two lists in one array
    ls[0].add("1");  ls[0].add("2");  ls[0].add("3");
    ls[1].add("4");  ls[1].add("5");  ls[1].add("6");

    // create two threads 
    Runnable[] t = new Runnable[2]; 
    for (int i = 0; i < 2; i++) {
      t[ i ] = new Runnable() {
        public void run() {
          pleasePrint( ls[i] );
        }
      };
      new Thread( t[i] ).start();
    }
  }
  void pleasePrint( List< String > ss )
  {
    for (int i = 0; i < ss.size(); i++) {
      System.out.print(ss.get(i)); // print the elements of one list
    }
  }
}

public class Threadtest {
  public static void main(String[] args) {
    myClass mc = new myClass();
    mc.doProcess();
  }
}

请注意,我的大代码如下所示.我的意思是在一种方法doProcess()中,我创建了一个列表数组并将项放入其中.然后,我想创建线程并将每个列表传递给一个方法.可以将数组和列表定义为私有类成员.但是,我想用这种方式.

Please note, my big code looks like this. I mean in one method, doProcess(), I create an array of lists and put items in it. Then I want to create threads and pass each list to a method. It is possible to define the array and lists as private class members. But, I want to do that in this way.

一切似乎都很正常,但是,在调用pleasePrint()时出现此错误:

Everything seems to be normal, however, I get this error at calling pleasePrint():

error: local variables referenced from an inner class must be final or effectively final
      pleasePrint( ls[i] );

我该如何解决?

推荐答案

出现此错误的原因很简单,而且很清楚地提到-从内部类引用的局部变量必须是final或有效的final.反过来,这是因为语言规范是这样说的.

The reason you are getting this error is straightforward and clearly mentioned - local variables referenced from an inner class must be final or effectively final. This is, in turn, because, the language specification says so.

在此处引用 Guy Steele :

实际上,原型实现 did 允许使用非最终变量 从内部类中引用.有人强烈抗议 用户,抱怨他们不想要这个!原因很有趣:为了支持这样的变量,有必要 堆分配它们,以及(至少在那时)平均Java 程序员对堆分配和垃圾仍然很不满意 收集等等.他们不赞成该语言的表演 没有发生堆分配表下" 出现了新"关键字.

Actually, the prototype implementation did allow non-final variables to be referenced from within inner classes. There was an outcry from users, complaining that they did not want this! The reason was interesting: in order to support such variables, it was necessary to heap-allocate them, and (at that time, at least) the average Java programmer was still pretty skittish about heap allocation and garbage collection and all that. They disapproved of the language performing heap allocation "under the table" when there was no occurrence of the "new" keyword in sight.

就您的实现而言,我宁愿使用列表列表,也不愿使用列表列表.

As far as your implementation goes, instead of using an array of list, I'd rather use a list of lists.

private final List<List<String>> mainList = new ArrayList<>();

您可以创建新列表并将其插入到构造函数中的主列表中,具体取决于所需的列表数量.

You can create new lists and insert them into the main list in the constructor depending on the number of lists you want.

public ListOfLists(int noOfLists) {
    this.noOfLists = noOfLists;
    for (int i = 0; i < noOfLists; i++) {
        mainList.add(new ArrayList<>());
    }
}

然后您可以按以下方式更改doProcess()方法:

You can then change your doProcess() method as follows:

public void doProcess() {
    for (int i = 0; i < noOfLists; i++) {
        final int index = i;
        // Using Lambda Expression as it is much cleaner
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName());
            pleasePrint(mainList.get(index));   // Pass each list for printing
        }).start();
    }
}

注意:我使用了一个名为noOfLists的实例变量(顾名思义)来存储所需的列表数量.如下所示:

Note: I used an instance variable named noOfLists to (as the name suggests) store the number of lists I need. Something as follows:

private final int noOfLists;

要填充列表,您可以执行以下操作:

To populate the list, you could do:

mainList.get(0).add("1");
mainList.get(0).add("2");
mainList.get(0).add("3");
mainList.get(1).add("4");
mainList.get(1).add("5");
mainList.get(1).add("6");
// And so on...

您将获得如下输出:

Thread-0
1
2
3
Thread-1
4
5
6

希望这会有所帮助:)

这篇关于使用Runnable通过多个线程运行方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆