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