多线程不工作 - 创建每循环索引Java的线程

时间:2017-11-14 23:28:47

标签: java multithreading

我编写了下面的代码试图运行两个线程来调用for循环中的函数,但是结果与我在没有多个线程的情况下顺序运行它的时间相同。有什么想法为什么这里的多线程不起作用?有没有更好的方法呢?例如,如果我想拥有10个线程,使用我的代码这意味着我必须在创建线程时创建10个重复的run()函数,我想知道是否有更简单的方法来设置线程数?也可以根据循环计数器创建一些线程,这样每个循环都会创建一个线程来完成它,所以如果我有10个循环,那么10个线程会同时运行以完成处理的速度非常快?

   private Thread t1 = new Thread(){
   public void run(){

            for (int i = 0; i < 2; i++)
            {
                try {
                    myfn(i);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    };

    private Thread t2 = new Thread(){
        public void run(){

            for (int i = 2; i < 4; i++)
            {
                try {
                    myfn(i);
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
            }
    };

 public Results getResults() throws IOException, SocketTimeoutException {

        t1.start();
        t2.start();
        try {
            t1.join(0);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        try {
            t2.join(0);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

4 个答案:

答案 0 :(得分:1)

为了跨多个线程运行相同的任务,您可能正在寻找一个线程池。 Java为此提供了ThreadPoolExecutor

Here是对Java并发的介绍,其中包含以下示例:

ExecutorService executor = Executors.newFixedThreadPool(1);

Future<Integer> future = executor.submit(() -> {
    try {
        TimeUnit.SECONDS.sleep(2);
        return 123;
    }
    catch (InterruptedException e) {
        throw new IllegalStateException("task interrupted", e);
    }
});

future.get(1, TimeUnit.SECONDS);

该示例专门创建一个只包含单个线程的池,但Executors.newFixedThreadPool的参数控制将使用多少线程。

我不确定你原来的问题为什么你认为没有使用两个线程。

答案 1 :(得分:1)

public class MyThead extend Thread{
    private int initValue = 0;
    private int upperBound = 0;

    public MyThread(int init, int ub){
        this.initValue = init;
        this.upperBound = ub;
    }
    public void run(){
        for(int i = init; i < upperBound; i++){
            myfn(i);
        }
    }
}

创建线程并启动它们:

List<Thread> threads = new ArrayList<>();
threads.add(new MyThread(0,2));
threads.add(new MyThread(2,4));

for(Thread t: threads){
    t.start()
}

for(Thread t: threads){
    t.join();
}

答案 2 :(得分:0)

您不需要复制线程/循环10次,只需采用逻辑并正确使用它。

public class ExampleThread extends Thread {
  private final int start, iterations;
  public ExampleThread(int start, int iterations) {
    this.start = start;
    this.iterations = iterations;
  }
  @Override public void run() {
    for (int i = 0; i < iterations; i++) {
      myfn(start + i);
    }
  }
}

int iterations = 2;
List<Thread> threads = new ArrayList<>();
for (int threadId = 0; threadId < 10; threadId++) {
  threads.add(new ExampleThread(threadId * iterations, iterations));
}
threads.forEach(Thread::start);
threads.forEach(t -> {
  try {
    t.join(0);
  } catch (Exception e) {
    e.printStackTrace(System.err);
  }
});

答案 3 :(得分:0)

  

我编写了下面的代码,尝试运行两个线程来调用for循环中的函数,但结果与我在没有多个线程的情况下顺序运行它的时间相同。

虽然很难在不看myfn(...)代码的情况下知道发生了什么,但有很多原因导致这种情况发生。以下是一些可能的原因:

  • 可能myfn运行得如此之快,以至于在不同的线程中运行它不会更快。
  • 可能是myfn正在等待某些其他资源,在这种情况下,线程无法真正并发运行。
  • 可能是myfn在IO(网络或磁盘)上阻塞,即使您一次执行2个(或更多),磁盘或远程服务器也无法处理请求更快。
  

有更好的方法吗?例如,如果我想拥有10个线程,使用我的代码,这将意味着我必须创建10个重复的run()函数......

这里做的正确的事情是创建自己的类,它采用下限和上限。正确的方法是实施Runnable,而不是扩展Thread。类似的东西:

public class MyRunnable implements Runnable {
    private final int start;
    private final int end;
    public MyRunnable(int start, int end) {
        this.start = start;
        this.end = end;
    }
    public void run() {
        for (int i = start; i < end; i++) {
            myfn(i);
        }
    }
}

然后您可以手动启动线程或使用ExecutorService,这样可以更轻松地维护线程:

// this will start a new thread for every job
ExecutorService threadPool = Executors.newCachedThreadPool();
threadPool.submit(new MyRunnable(0, 2));
threadPool.submit(new MyRunnable(2, 4));
// once you've submitted your last task, you shutdown the pool
threadPool.shutdown();
// then we wait until all of the tasks have run
threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);