如何在JAVA中减缓线程速度

5

我有一个类,在其中运行了一个for循环10次,这个类实现了Runnable接口。现在在main()中我创建了两个线程。现在两个线程都会运行循环直到10次。但是我想检查每个线程的循环计数。如果t1已经超过7,那么让它睡眠1秒钟,以便让t2完成。但如何实现这一点?请看代码。我尝试了,但看起来完全愚蠢。如何检查线程的数据?

class SimpleJob implements Runnable {
    int i;
    public void run(){
        for(i=0; i<10; i++){
            System.out.println(Thread.currentThread().getName()+" Running ");
        }        
    }

    public int getCount(){
        return i;
    }
}
public class Threadings {
    public static void main(String [] args){
        SimpleJob sj = new SimpleJob();
        Thread t1 = new Thread(sj);
        Thread t2 = new Thread(sj);

        t1.setName("T1");
        t2.setName("T2");

        t1.start();
        try{
            if(sj.getCount() > 8){ // I know this looks totally ridiculous, but then how to check variable i being incremented by each thread??
                System.out.println("Here");
                Thread.sleep(2000);
            }            
        }catch(Exception e){
            System.out.println(e);
        }
        t2.start();
    }    
}

请帮忙


有没有一种方法可以确定哪个线程在给定时刻运行代码?如果有的话,那么可以使用if语句来增加每个线程的值。 - BlackVegetable
2
有很多问题。你为什么要在多个线程中执行相同的任务?你为什么想要“减慢”计算速度?你试图解决的问题不清楚,也许如果你解释一下你想要实现什么目标,就能得到更好的答案。 - Jochen
@blackVegetable:抱歉,我是Java的完全新手。恐怕我无法理解你所说的内容 :( - Shades88
3
作为一个完全的新手,你应该避免使用共享数据的线程,先阅读一篇关于进程同步的入门文章。这是一个直觉解决问题很可能会有微妙错误的领域之一。 - millimoose
2
你有以下三个问题:1)在两个不同的线程中修改相同的变量i,2)在需要忙等待的情况下使用了if而不是while,3)延迟主线程而不是目标线程。请先阅读有关线程的更多信息,然后再尝试,因为这里有太多错误了。 - Erik
显示剩余7条评论
3个回答

7

您应该使用一些同步对象,而不是依赖于线程的减速。我强烈建议您查看java.util.concurrent包中的一个类。您可以使用CountdownLatch - 线程1将等待它,线程2将执行倒计时并释放锁,让线程1继续(释放应在线程2代码结束时进行)。


0

如果目标是并行运行2个Runnable(作为线程)并等待它们都完成,您可以按递增的复杂度/功率使用以下方法:

  1. 使用Thread.join(如@Suraj Chandran建议的,但他的回复似乎已被删除)
  2. 使用CountDownLatch(也由@zaske建议)
  3. 使用ExecutorService.invokeAll()

编辑添加

首先,我不明白神奇的“如果你在7那里就等待另一个”的逻辑是什么。但是,要从您的主代码中使用Thread.join(),代码将如下所示

t1.start();  // Thread 1 starts running...
t2.start();  // Thread 2 starts running...

t1.join();   // wait for Thread 1 to finish
t2.join();   // wait for Thread 2 to finish

// from this point on Thread 1 and Thread 2 are completed...

好的,我可以使用join,但是什么时候使用呢?我希望当任何一个线程的i大于或等于7时,它应该在结尾处加入。我该如何实现这个? - Shades88

0
我添加了一个同步块,一次只能由一个线程进入。两个线程都调用并同时进入该方法。其中一个线程将赢得比赛并获取锁。第一个线程离开块后等待2秒钟。在此期间,第二个线程可以迭代循环。我认为这种行为是想要的。如果第二个线程不必等待2秒钟,您可以设置一些布尔标志,表示第一个线程完成了块,并在if语句中使用此标志,以防止第二个线程的等待时间。
class SimpleJob implements Runnable {
int i;
public void run(){

    synchronized (this) {
        for(i=0; i<8; i++){
            System.out.println(Thread.currentThread().getName()+" Running ");
        } 
    } 

    try {
        System.out.println("Here");
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    for(i=0; i<2; i++){
        System.out.println(Thread.currentThread().getName()+" Running ");
    }
}

public int getCount(){
    return i;
}
}

public class Threadings {
public static void main(String [] args){
    SimpleJob sj = new SimpleJob();
    Thread t1 = new Thread(sj);
    Thread t2 = new Thread(sj);

    t1.setName("T1");
    t2.setName("T2");

    t1.start();
    t2.start();
}    
}

+1 表示向我展示代码。还有一个问题,如果任何一个线程 t1 超过 7,那么它应该在最后加入的条件在哪里? - Shades88
1
两个线程不会合并。第二个线程必须等待第一个线程离开同步块。同步块使用对象(“this”)作为锁。 - C12-H22-O11
谢谢,太棒了。现在我可以通过这段代码学到更多。再次感谢。 - Shades88
你只是转载了这段代码。能说说你做了什么,OP哪里出了问题吗?否则的话我会投-1。 - Gray
1
前8个循环中,由于它们共享一个锁,所以这两个线程是串行而不是并行运行的。虽然对于学习有一定用处,但这不是非常有用的代码。 - user949300
我误解了问题,非常抱歉。两者应该完全并行运行,t1应该标识自己并休眠1秒钟。 - C12-H22-O11

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接