[英]Threads synchronization in Java
我有一个类似的场景。...有四个线程分别命名为Thread1,Thread2,Thread3和Thread4。 并且有一个计数器变量。 我想输出如下
Thread1 : value of counter variable is = 0
Thread2 : value of counter variable is = 1
Thread3 : value of counter variable is = 2
Thread4 : value of counter variable is = 3
Thread1 : value of counter variable is = 4
Thread2 : value of counter variable is = 5
Thread3 : value of counter variable is = 6
Thread4 : value of counter variable is = 7
Thread1 : value of counter variable is = 8
Thread2 : value of counter variable is = 9
Thread3 : value of counter variable is = 10
Thread4 : value of counter variable is = 11
甚至我在逻辑上也做到了。 但是我想要类似的东西,当Thread1正在打印counter变量时,所有其余线程都应等待.....然后在Thread2之后出现图片并打印counter变量,其余应等待。
建议我为此的最佳解决方案。 提前致谢 :-)
除了了解同步,这几乎没有意义。 我会使用CyclicBarrier
来做到这一点。 这是一个相当高级的抽象,因此您不必自己使用wait()
或notifiy()
。
或者,您可以使用Integer
或AtomicInteger
对象作为变量,并将其传递到线程周围(每个对象都应提供可被另一个线程调用的consume(Integer i)
方法,然后递增并打印该值并将其传递给下一个螺纹)。 在此变体中,同步在代码中隐式处理。
我不确定你想要什么。 您是否要让线程按顺序增加并打印变量? 这没有任何意义,线程是独立的,并且可以同时运行。 那就是他们的目的。
因此,让我直接讲:您想使用并行处理来进行串行工作。
基本上,您要做的是:
for(int i=0;i<10;i++)
System.out.println(i);
但是然后有线程。
线程用于并行处理事务。 那就是他们的目的。 试图将串行问题强加给这个概念,不仅会减慢您的应用程序的速度,而且会使它更容易出错。
当然,除非您的这个示例非常简化。 也许您需要提供更多信息以帮助我们,然后...
这是一个有趣的问题,因为线程被设计为独立地并排工作,而不是严格地锁定在一起。
我认为最简单的方法是使用公平的ReentrantLock , AtomicInteger和一些谨慎的设置(以确保线程以正确的顺序开始在ReentrantLock上等待)。
您的主线程将需要初始化计数器,创建锁对象并对其进行锁定,然后依次启动四个子线程,确保在关闭下一个线程之前,每个子线程都到达了锁。
当所有4个线程准备就绪时,您可以释放锁并让其他线程运行。
每个工作线程应从计数器中获取值,将其递增,显示计数器,然后释放锁(这将使下一个线程运行),然后再重新获取它。
请注意,这里仍然存在竞争条件:线程2可能在线程1开始再次等待锁之前绕循环运行,因此这两个线程最终将以相反的顺序运行。 要解决此问题,辅助线程需要等待,直到有足够多其他线程在等待,直到它们在循环中继续进行为止(当然,最后一次迭代除外)。 不太好,但是由于列出的限制,我担心这很重要。
这不是简单的代码。 我认为,这里要学习的教训是,您不应该真正使用多个线程来执行固有的串行工作! 要么,要么您不必在乎哪个线程执行哪个串行操作。
我找到了解决此问题的两种方法。...但仍在等待专家评论...。
第一种方式:-----
包semafore;
导入java.util.concurrent.Semaphore;
公共类Main {公共静态void main(String args [])引发异常{Semaphore sem = new Semaphore(1,true); 线程thrdA = new Thread(new SyncOutput(sem,“ Thread1”)); 线程thrdB = new Thread(new SyncOutput(sem,“ Thread2”)); 线程thrdC =新线程(新SyncOutput(sem,“ Thread3”)); 线程thrdD =新线程(新SyncOutput(sem,“ Thread4”));
thrdA.start();
thrdB.start();
thrdC.start();
thrdD.start();
thrdA.join();
thrdB.join();
thrdC.join();
thrdD.join();
}
}
SyncOutput类实现Runnable {Semaphore sem; 字符串味精; 私有静态int val = 0;
SyncOutput(Semaphore s, String m) {
sem = s;
msg = m;
}
public void run() {
for (int i = 0; i < 3; i++){
try {
sem.acquire(1);
System.out.println(msg + " : " + ++val);
Thread.sleep(1000);
} catch (Exception exc) {
System.out.println("Error Writing File");
}
sem.release(1);
}
}
}
第二种方式:-----
包线程;
class num {
// state variable identifying whose turn it is.
private String whoseTurn ="A";
private int cnt=0;
public boolean writenum(String who) {
String x = Thread.currentThread().getName();
try{
Thread.sleep(1000);
}catch(Exception e){}
if (x.equalsIgnoreCase(whoseTurn)) {
System.out.println(x+":"+cnt++);
if(x.equalsIgnoreCase("A"))
whoseTurn = "B";
else if(x.equalsIgnoreCase("B"))
whoseTurn = "C";
else if( x.equalsIgnoreCase("C"))
whoseTurn = "D";
else if( x.equalsIgnoreCase("D"))
whoseTurn = "A";
}
return true;
}
}
public class Game {
public static void main(String args[]) {
num ob = new num();
Thread A = new Thread(new Player("A", ob));
Thread B = new Thread(new Player("B", ob));
Thread C = new Thread(new Player("C", ob));
Thread D = new Thread(new Player("D", ob));
A.setName("A");
B.setName("B");
C.setName("C");
D.setName("D");
A.start();
B.start();
C.start();
D.start();
try {
// Wait 5 seconds
Thread.currentThread().sleep(5000);
} catch (InterruptedException e) { }
ob.writenum("DONE"); // cause the players to quit their threads.
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) { }
}
}
class Player implements Runnable {
num area; // Table where they play
String who;
public Player(String who, num area) {
this.area = area;
this.who = who;
}
public void run() {
while (area.writenum(who));
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.