java中的并发循环
我想运行两个共享一个方法的线程来打印一些东西。我希望将此作为输出:java中的并发循环,java,multithreading,concurrency,Java,Multithreading,Concurrency,我想运行两个共享一个方法的线程来打印一些东西。我希望将此作为输出: a b a b a b 第一个线程打印一个“a”,第二个线程打印一个“b”。我设法打印了一次,但我不能包含一个适当的循环来交换打印 我编写了以下代码来执行此操作: public void run() { while(i<10) { synchronized(this) { while (turn!=turn) { try {
a b a b a b
第一个线程打印一个“a”,第二个线程打印一个“b”。我设法打印了一次,但我不能包含一个适当的循环来交换打印
我编写了以下代码来执行此操作:
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();
}
}
}
public void run(){
而
在while之前让其中一个线程休眠5秒。它将明确哪个线程的顺序
while
循环未执行,因为其条件始终为false
。将内部while
一起删除,您不需要它
不需要turn
变量。synchronize
和Thread.sleep(5)
将使线程轮流
捕获中断异常时,请至少放置一些println
一个简单的解决方案是使用,它将执行所有所需的等待和通知操作:
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谦卑地指出的那样,它使用的是一种效率不高的方法
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();
}
}
据我所知,这保证没有死锁,但如果其中一个线程没有终止,因为另一个线程正在等待,则可能会出现饥饿。但是,对于这样一个简单的示例来说,这不应该是一个问题。监视器也更倾向于使用轮询,但要稍微复杂一些。现在是凌晨3:30,我不想去哦,睡觉。
这就是我想到的:
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();
}
}
}
运行它的一种方法是:
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
将保留该回合的记忆,并在其上进行同步,允许你在该回合中做你必须做的事情,然后你可以切换回合。线程。睡眠
只是让你以很好的速度查看打印。
System.out.println(toPrint);
是您的printThreadOutput();
附言:欢迎就如何改进代码提出建议。while(turn!=turn)
?synchronized
应该解决非迂回代码中包含混合制表符和空格的缩进问题–这是一个坏主意。您应该确保一致使用制表符或空格。您发布的代码有什么问题?另外,while(turn!=turn)
的计算结果仅为while(false)
,这意味着所有的代码都永远不会执行。啊,忙旋转锁。我也有你的代码的经验,这非常有用。“同步和线程。睡眠(5)将使线程轮流”。严格来说,这不是真的。大多数JVM在调用线程时都会执行上下文切换。sleep
,但不能保证在该线程睡眠时另一个线程会运行。如果要保证这种行为,您应该始终拥有一个控制变量。好吧!根据您的说明,它工作得很好。谢谢