多线程不起作用-创建每个循环的线程索引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();
}

我写了下面的代码,试图运行两个线程来调用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);

您不需要复制线程/循环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);
}
});

最新更新