簡體   English   中英

多線程不起作用-為每個循環索引Java創建線程

[英]Multithreading not working - Create thread per loop index Java

我編寫了以下代碼,嘗試運行兩個線程以在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();
        }

為了在多個線程中運行同一任務,您可能正在尋找一個線程池。 Java為此提供了一個ThreadPoolExecutor

是帶有以下示例的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的參數控制將使用多少個線程。

從您最初的問題中我不能確定為什么您認為沒有利用兩個線程。

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();
}

您不需要復制線程/循環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);
  }
});

我編寫了以下代碼,嘗試運行兩個線程以在for循環中調用函數,但是結果的時間相同,就好像我沒有多個線程地按順序運行它一樣。

盡管沒有看到myfn(...)代碼很難知道發生了什么,但是有很多原因可以導致這種情況發生。 以下是一些可能的原因:

  • 可能是myfn運行得如此之快,以至於在不同線程中運行它的速度不會更快。
  • 可能是myfn正在等待其他資源,在這種情況下,線程不能真正並發運行。
  • 可能是myfn阻塞了IO(網絡或磁盤),即使您一次執行兩個(或多個),磁盤或遠程服務器也無法更快地處理增加的請求。

有更好的方法嗎? 例如,如果我想擁有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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM