以下程序执行基本的多线程任务。我在一个类中有两个线程。一个线程执行增加值变量的工作,另一个线程检查值并显示消息。
Class Was{
private int ctime;
private int value;
public Thread w,c;
public was(int a) {
ctime=a;
w = new Thread(new Runnable() {
public void run() {
try {
for(int i=0;i<5;i++) {
Thread.sleep(ctime*1000);
value++;
}
System.out.printf("\nIncreasing done");
} catch(InterruptedException e) {
System.out.println(e);
}
}
});
c = new Thread(new Runnable() {
public void run() {
try {
for(;;) {
if(value==3) {
w.wait();
System.out.printf("\nValue reached");
w.notify();
break;
}
}
} catch(InterruptedException e) {
System.out.println(e);
}
}
});
}
main class
class Main{
public static void main(String z[]) {
Scanner s = new Scanner(System.in);
int temp;
System.out.printf("\nEnter the sleeping time in seconds: ");
temp=s.nextInt();
was m = new was(temp);
m.w.start();
m.c.start();
}
}
c线程从不告诉已达到该值。我不明白为什么。
答案 0 :(得分:8)
c线程从不告诉已达到该值。我不明白为什么。
在线程之间共享值时,需要使用某种机制来同步保存该值的内存。这可以使用synchronize
块来完成,将值标记为volatile
,或使用(在这种情况下)AtomicInteger
。这是一个good tutorial on the memory consistency。
AtomicInteger
在这里使用是正确的,因为它允许线程安全地增加。你必须记住,增量是不原子操作,因为它实际上是获取,增量和设置。
您的代码看起来像:
private final AtomicInteger value = new AtomicInteger(0);
...
value.incrementAndGet();
...
if (value.get() == 3) ...
另外,正如@Boris所指出的,你有以下代码:
w.wait();
System.out.printf("\nValue reached");
w.notify();
这不会编译,因为您不在synchronized
块中。此外,拥有wait()
然后notify()
是一种奇怪的模式。您可能还想阅读tutorial on guarded blocks。
答案 1 :(得分:0)
我对代码,相同要求但不同设计进行了更改。所以我理解的是,线程W和C应该共享同一个监视器,通过该监视器,当其他信号发出时,会通知它。因此,在这种情况下,对象锁定充当监视器。我将同一个Object(lock)实例传递给两个线程,并在该锁上调用wait和notify。它工作正常。 package com.stackoverflow.gin;
public class Main {
private Object lock = new Object();
private C c = new C(lock);
private W w = new W(lock);
public static void main(String[] args) {
Main u = new Main();
u.start();
}
public void start() {
System.out.println("Start");
c.start();
w.start();
}
public class W extends Thread {
private Object lock;
public W(Object lock) {
this.lock = lock;
}
@Override
public void run() {
try {
for (;;) {
Thread.sleep(1000);
System.out.println("Notify C that I have finished work");
synchronized (lock) {
lock.notify();
}
}
} catch (Exception e) {
System.out.println(e.getMessage() + "W");
}
}
}
public class C extends Thread {
private int times = 0;
private Object lock;
public C(Object lock) {
this.lock = lock;
}
@Override
public void run() {
try {
for (;;) {
System.out.println("Waiting for W to finish ");
synchronized (lock) {
lock.wait();
}
System.out.println("W has notified " + times);
times++;
if (times == 3) {
System.out.println("Every thing is done, lets die to gether");
System.exit(0);
}
}
} catch (Exception e) {
System.out.println(e);
}
}
}
}
答案 2 :(得分:0)
我认为你不能或者应该从其他线程中等待一个线程。它像两辆公共汽车并行运行,一辆公共汽车想在其他公交车上运行。那没有意义。或者它不是一个好的设计。我不知道以下是你在寻找什么,但看看,让我知道。
import java.util.concurrent.atomic.AtomicInteger;
public class Main {
private Object lock = new Object();
private C c = new C(lock);
private W w = new W(lock);
private AtomicInteger times = new AtomicInteger();
public static void main(String[] args) {
Main u = new Main();
u.start();
}
public void start() {
System.out.println("Start");
c.start();
w.start();
}
public class W extends Thread {
private Object lock;
public W(Object lock) {
this.lock = lock;
}
@Override
public void run() {
try {
for (int i = 0; i < 5; i++) {
Thread.sleep(1000);
times.set(i + 1);
System.out.println("Incremented counter " + times.get());
}
synchronized (lock) {
System.out.println("Notify C that I have finished work");
lock.notify();
}
} catch (Exception e) {
System.out.println(e.getMessage() + "W");
}
}
}
public class C extends Thread {
private Object lock;
public C(Object lock) {
this.lock = lock;
}
@Override
public void run() {
try {
for (;;) {
if (times.get() == 3) {
synchronized (lock) {
System.out.println("Now I will wait until W finishes with his work");
lock.wait();
System.out.println("Ok W is finished with the loop " + times.get() + " lets exit the sytem.");
System.exit(0);
}
}
}
} catch (Exception e) {
System.out.println(e);
}
}
}
}