首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >java中的并发循环

java中的并发循环
EN

Stack Overflow用户
提问于 2013-03-31 08:50:52
回答 3查看 1.6K关注 0票数 0

我想运行两个线程,这两个线程共享一个方法,以打印出一些东西。我希望将以下内容作为输出:

代码语言:javascript
复制
a b a b a b 

第一个线程打印'a‘,第二个线程打印'b’。我设法打印了一次,但我不能包括一个适当的循环来交换指纹。

我写了这段代码来执行下面的代码:

代码语言:javascript
复制
public void run() {
    while(i<10) {
        synchronized(this) {
            while (turn!=turn) {
                try {
                    turn=!turn;
                    wait();
                    sleep(10);
                }
                catch(InterruptedException ie){}
            }

            printThreadOutput();
            turn=!turn;
            i++;
            notifyAll();
        }
    }
}

有什么建议吗?

EN

回答 3

Stack Overflow用户

发布于 2013-03-31 09:20:16

一个简单的解决方案是使用java.util.concurrent.locks.Lock,它将执行所需的所有等待和通知操作:

代码语言:javascript
复制
public class ThreadTest {

    private static final Lock lock = new ReentrantLock();

    public static final void main(String[] args) {
        Runnable aRun;
        Runnable bRun;

        aRun = new Runnable() {
            public void run() {
                while (true) {
                    lock.lock();
                    System.out.println("a");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                    lock.unlock();
                }
            }
        };

        bRun = new Runnable() {
            public void run() {
                while (true) {
                    lock.lock();
                    System.out.println("b");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                    lock.unlock();
                }
            }
        };

        Thread aThread = new Thread(aRun);
        Thread bThread = new Thread(bRun);
        aThread.start();
        bThread.start();
    }

}

不使用监视器你也可以这样做,但正如@noahz谦虚地指出的那样,它使用的Spinlock效率不高。

代码语言:javascript
复制
public class ThreadTest {

    private static volatile Boolean isATurn = true;

    public static void main(String[] args) {
        Runnable aRun;
        Runnable bRun;

        aRun = new Runnable() {
            public void run() {
                while (true) {
                    while (!isATurn) {
                    }
                    System.out.println("a");
                    isATurn = false;
                }
            }
        };

        bRun = new Runnable() {
            public void run() {
                while (true) {
                    while (isATurn) {
                    }
                    System.out.println("b");
                    isATurn = true;
                }
            }
        };

        Thread aThread = new Thread(aRun);
        Thread bThread = new Thread(bRun);
        aThread.start();
        bThread.start();
    }

}

据我所知,这保证了不会出现死锁,但如果其中一个线程没有终止,则可能会出现饥饿,因为另一个线程将在等待它。然而,对于这样一个简单的例子来说,这不应该是一个问题。监视器也比使用轮询更可取,但是稍微复杂一些。

票数 1
EN

Stack Overflow用户

发布于 2013-03-31 09:29:52

现在是凌晨三点半,我想睡觉了。这是我想出来的:

代码语言:javascript
复制
class TurnHolder {

    private volatile int currentTurn;

    public void setNextTurn() {
    this.currentTurn = currentTurn^1;
    }

    public int getCurrentTurn() {
    return currentTurn;
    }
}

class Printer implements Runnable {

    private String toPrint;
    private TurnHolder sharedResource;
    private int turn;

    Printer(String toPrint, TurnHolder sharedResource, int turn) {
    this.toPrint = toPrint;
    this.sharedResource = sharedResource;
    this.turn = turn;
    }

    @Override
    public void run() {

    while (true) {
        synchronized (sharedResource) {
        if (sharedResource.getCurrentTurn() != turn)
            try {
            sharedResource.wait();
            } catch (InterruptedException e) {
            e.printStackTrace();
            }
        System.out.println(toPrint);
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        sharedResource.setNextTurn();
        sharedResource.notifyAll();
        }
    }

    }

运行它的一种方法是:

代码语言:javascript
复制
TurnHolder sharedResource = new TurnHolder();

Printer printerA = new Printer("a", sharedResource, 0);
Printer printerB = new Printer("b", sharedResource, 1);

new Thread(printerA).start();
new Thread(printerB).start();

这样,你的sharedResource将保持转弯的记忆,同步它允许你在该转弯时做你必须做的事情,然后你可以切换转弯。Thread.sleep只是为了让你能以很快的速度看到打印结果。System.out.println(toPrint);就是您的printThreadOutput();

附言:欢迎就如何改进代码提出建议。

票数 1
EN

Stack Overflow用户

发布于 2013-03-31 09:20:12

  1. 使其中一个线程提前5秒休眠。它将明确哪个将是线程顺序。
  2. while循环没有执行,因为它的条件始终为false。完全删除内部的while,你不需要它。
  3. turn变量是不需要的。在捕获InterruptedException.

时,synchronizeThread.sleep(5)将使线程轮流使用。

  • 至少放入一些println
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15725207

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档