![](/img/trans.png)
[英]Thread synchronization/producer-consumer in java. Printing out numbers 1-10 then 10-1 repeatedly
[英]Java Thread synchronization - printing out numbers in right order
我正在学习如何在Java中使用线程,我需要一些建议。
我想在0..50的标准输出数字上打印使用三个线程完成的线程的名称。
我有两个类-实现Runnable的Counter 类和创建并运行线程的Main类 。 计数器具有在线程之间共享的变量c 。
我的想法是,我将c加1,然后在当前线程上调用yield() ,以便其他线程也可以这样做。 重复此操作,直到c达到50。
但这不起作用,数字打印顺序错误。 我该如何解决?
public class Counter implements Runnable {
Thread t1;
private int c = -1;
public Counter() {
}
public Counter(String name) {
t1 = new Thread(this, name);
t1.start();
}
@Override
public void run() {
while (c < 50) {
increment();
Thread.yield();
}
}
public void increment() {
if (c < 50) {
c++;
System.out.println(Thread.currentThread().getName() + ": " + c);
}
}
}
public class Main {
public static void main(String[] args) throws IllegalThreadStateException {
Counter c1 = new Counter();
Thread t1 = new Thread(c1, "Thread 1");
Thread t2 = new Thread(c1, "Thread 2");
Thread t3 = new Thread(c1, "Thread 3");
t1.start();
t2.start();
t3.start();
}
编辑:最终我以这种方式解决了它。 谢谢所有帮助我艰难地开始多线程工作的人。
import java.util.concurrent.atomic.AtomicInteger;
public class Counter2 implements Runnable {
// you could also use simple int
private AtomicInteger c = new AtomicInteger(-1);
private static final Object syncObject = new Object();
public Counter2() {
}
@Override
public void run() {
while (c.get() < 50) {
synchronized (syncObject) {
if (c.get() < 50) {
System.out.println(Thread.currentThread().getName() + ": " + c.incrementAndGet());
}
}
}
}
}
在带有特殊静态对象的方法增量中使用同步部分。
private static final Object syncObj = new Object();
public void increment()
{
syncrhonized( syncObj )
{
c++;
System.out.println(c);
}
}
或通过其声明使此方法同步。
但是将实际数据存储在线程对象中是错误的想法。 线程应该只使用共享对象进行操作,而不要存储它们。\\实际上我不明白为什么要在其中启动线程
使increment()
同步,以防止其他线程同时进入方法。
与yield()
结合使用,您应该能够使另一个线程打印下一个数字(并非总是如此,因为系统可能会再次恢复调用yield
的线程-请参阅Ingo的答案-,但顺序应相同)。
synchronized increment()
意味着,如果另一个线程通过输入方法已经获取了锁,则试图在同一对象上输入该方法的任何线程都必须等待。
引用javadoc Thread.yield(),我强调:
public static void yield()
给调度程序的提示是当前线程愿意放弃当前使用的处理器。 调度程序可以随意忽略此提示 。
...
很少适合使用此方法。
是的,您的代码无效。 Thread#yield()不会以您期望的方式控制线程调度程序。 我很好奇您会得到什么结果。您可能会得到重复的数字,有些数字会有些混乱。
您可以使用原子整数,该整数应删除所有重复项。 但是由于print语句不是原子的。 您仍然可以不按顺序打印结果。 因此,您可能应该仅同步增量方法。 另外,您实际上并不需要产量,所以将其丢弃。
如果问题的目的是从线程1到线程2再到线程3再回到线程1,依此类推,那么结果是
Thread 1:0
Thread 2:1
Thread 3:2
Thread 1:3
Thread 2:4
Thread 3:5
Thread 1:6
Thread 2:7
....
然后,您需要锁定增量方法,并使用wait和notifyAll。 等待将导致其他线程停止处理,直到当前线程通知它们再次启动。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.