Java同一资源中的线程同步问题
Java Thread Synchronization problem in same resource
我正在尝试使用两个线程对同一个源进行操作。我为它设计了一个典型的生产者和消费者问题。在与生产者设置资源class中的值时,我想与消费者一一获取设置值。我想要的输出应该是这样的:
Producer -> Setting data = 0
Consumer -> Getting data = 0
Producer -> Setting data = 1
Consumer -> Getting data = 1
Producer -> Setting data = 2
Consumer -> Getting data = 2
Producer -> Setting data = 3
Consumer -> Getting data = 3
Producer -> Setting data = 4
Consumer -> Getting data = 4
这是我的资源 class:
public class Resource{
private int value;
private boolean current = false;
public synchronized void setValue(int val) {
while(current == true) {
try {
wait();
}catch(Exception ex) {}}
value = val;
current = true;
notifyAll();
}
public synchronized int getValue() {
while(current == false) {
try {
wait();
}catch(Exception ex) {}}
current = false;
notifyAll();
return value;
}
}
主要方法和生产者、消费者class在这里:
class Producer extends Thread{
private Resource rs;
public Producer(Resource rs1) {
rs = rs1;
}
public void run() {
for(int i = 0 ; i < 5 ; i++) {
rs.setValue(i);
System.out.println("Producer -> Setting data = " + i);
try {
sleep(100);
}catch(Exception ex){
ex.printStackTrace();
}
}
}
}
class Consumer extends Thread{
private Resource rs;
public Consumer(Resource rs1) {
rs = rs1;
}
public void run() {
int value = 0;
for(int i = 0 ; i < 5; i++) {
value = rs.getValue();
System.out.println("Consumer -> Getting data= " + i);
try {
sleep(100);
}catch(Exception ex) {
ex.printStackTrace();
}
}
}
}
public class Dependent {
public static void main(String[] args) throws IOException {
Resource res = new Resource();
Producer p1 = new Producer(res);
Consumer c1 = new Consumer(res);
p1.start();
c1.start();
}
}
虽然我在资源class的方法中使用了synchronized、wait和notifyAll关键字,线程继续工作而不互相等待。我在哪里犯了错误?我在java一本书上看过类似这个代码示例的代码示例,好像没有问题。
当我在不添加当前布尔变量的情况下编写代码时,代码甚至无法运行。这就是为什么我必须通过从书中查找来添加它。线程不需要检查当前值就同步工作吗?
他们做互相等待,但是线程同步操作多,多比Thread.sleep(100 ) 所以你无法分辨。您的测试代码打印 'i' 而不是 'value',这是值得怀疑的。在这些线程之一(例如,在消费者中)摆脱 Thread.sleep(100)
,你会发现消费者仍然需要大约半秒才能完成 - 因为每次它都会等待大约 100 毫秒在资源上调用 .getValue()
,因为该调用将阻塞(卡在 wait() 循环中)直到生产者调用 .setValue ,它每 100 毫秒只执行一次。
您的资源对象 'works',某些值 'works',但设计非常糟糕,从核心库重新创建现有的并更好地实现 类,例如java.util.concurrent.Latch
,忽略中断,只会盲目地等待。
他们的 API 的命名也有点奇怪,因为 get 调用有相当大的副作用。 get
更像是一个 get and clear
操作:在一个 get 操作之后,另一个 get 操作将永远冻结线程,或者至少,直到某个线程设置一个值。
你怎么看?
import java.io.IOException;
class Resource {
private volatile Integer value;
public synchronized void setValue(int val) {
while(value != null && !value.equals(val)) {
try {
wait();
}catch(Exception ex) {}}
value = val;
notifyAll();
}
public synchronized int getValue() {
while(value == null) {
try {
wait();
}catch(Exception ex) {}}
int answer = value;
value = null;
notifyAll();
return answer;
}
}
class Producer extends Thread{
private Resource rs;
public Producer(Resource rs1) {
rs = rs1;
}
public void run() {
for(int i = 0 ; i < 5 ; i++) {
rs.setValue(i);
System.out.println("Producer -> Setting data = " + i);
try {
sleep(100);
}catch(Exception ex){
ex.printStackTrace();
}
}
}
}
class Consumer extends Thread{
private Resource rs;
public Consumer(Resource rs1) {
rs = rs1;
}
public void run() {
for(int i = 0 ; i < 5; i++) {
int value = rs.getValue();
System.out.println("Consumer -> Getting data= " + value);
try {
sleep(100);
}catch(Exception ex) {
ex.printStackTrace();
}
}
}
}
public class Dependent {
public static void main(String[] args) throws IOException {
Resource res = new Resource();
Producer p1 = new Producer(res);
Consumer c1 = new Consumer(res);
p1.start();
c1.start();
}
}
或
class Resource {
private static final int WAIT_VALUE = -1;
private volatile int value = WAIT_VALUE;
public synchronized void setValue(int val) {
while(value > WAIT_VALUE && value != val) {
try {
wait();
}catch(Exception ex) {}}
value = val;
notifyAll();
}
public synchronized int getValue() {
while(value == WAIT_VALUE) {
try {
wait();
}catch(Exception ex) {}}
int answer = value;
value = WAIT_VALUE;
notifyAll();
return answer;
}
}
我正在尝试使用两个线程对同一个源进行操作。我为它设计了一个典型的生产者和消费者问题。在与生产者设置资源class中的值时,我想与消费者一一获取设置值。我想要的输出应该是这样的:
Producer -> Setting data = 0
Consumer -> Getting data = 0
Producer -> Setting data = 1
Consumer -> Getting data = 1
Producer -> Setting data = 2
Consumer -> Getting data = 2
Producer -> Setting data = 3
Consumer -> Getting data = 3
Producer -> Setting data = 4
Consumer -> Getting data = 4
这是我的资源 class:
public class Resource{
private int value;
private boolean current = false;
public synchronized void setValue(int val) {
while(current == true) {
try {
wait();
}catch(Exception ex) {}}
value = val;
current = true;
notifyAll();
}
public synchronized int getValue() {
while(current == false) {
try {
wait();
}catch(Exception ex) {}}
current = false;
notifyAll();
return value;
}
}
主要方法和生产者、消费者class在这里:
class Producer extends Thread{
private Resource rs;
public Producer(Resource rs1) {
rs = rs1;
}
public void run() {
for(int i = 0 ; i < 5 ; i++) {
rs.setValue(i);
System.out.println("Producer -> Setting data = " + i);
try {
sleep(100);
}catch(Exception ex){
ex.printStackTrace();
}
}
}
}
class Consumer extends Thread{
private Resource rs;
public Consumer(Resource rs1) {
rs = rs1;
}
public void run() {
int value = 0;
for(int i = 0 ; i < 5; i++) {
value = rs.getValue();
System.out.println("Consumer -> Getting data= " + i);
try {
sleep(100);
}catch(Exception ex) {
ex.printStackTrace();
}
}
}
}
public class Dependent {
public static void main(String[] args) throws IOException {
Resource res = new Resource();
Producer p1 = new Producer(res);
Consumer c1 = new Consumer(res);
p1.start();
c1.start();
}
}
虽然我在资源class的方法中使用了synchronized、wait和notifyAll关键字,线程继续工作而不互相等待。我在哪里犯了错误?我在java一本书上看过类似这个代码示例的代码示例,好像没有问题。
当我在不添加当前布尔变量的情况下编写代码时,代码甚至无法运行。这就是为什么我必须通过从书中查找来添加它。线程不需要检查当前值就同步工作吗?
他们做互相等待,但是线程同步操作多,多比Thread.sleep(100 ) 所以你无法分辨。您的测试代码打印 'i' 而不是 'value',这是值得怀疑的。在这些线程之一(例如,在消费者中)摆脱 Thread.sleep(100)
,你会发现消费者仍然需要大约半秒才能完成 - 因为每次它都会等待大约 100 毫秒在资源上调用 .getValue()
,因为该调用将阻塞(卡在 wait() 循环中)直到生产者调用 .setValue ,它每 100 毫秒只执行一次。
您的资源对象 'works',某些值 'works',但设计非常糟糕,从核心库重新创建现有的并更好地实现 类,例如java.util.concurrent.Latch
,忽略中断,只会盲目地等待。
他们的 API 的命名也有点奇怪,因为 get 调用有相当大的副作用。 get
更像是一个 get and clear
操作:在一个 get 操作之后,另一个 get 操作将永远冻结线程,或者至少,直到某个线程设置一个值。
你怎么看?
import java.io.IOException;
class Resource {
private volatile Integer value;
public synchronized void setValue(int val) {
while(value != null && !value.equals(val)) {
try {
wait();
}catch(Exception ex) {}}
value = val;
notifyAll();
}
public synchronized int getValue() {
while(value == null) {
try {
wait();
}catch(Exception ex) {}}
int answer = value;
value = null;
notifyAll();
return answer;
}
}
class Producer extends Thread{
private Resource rs;
public Producer(Resource rs1) {
rs = rs1;
}
public void run() {
for(int i = 0 ; i < 5 ; i++) {
rs.setValue(i);
System.out.println("Producer -> Setting data = " + i);
try {
sleep(100);
}catch(Exception ex){
ex.printStackTrace();
}
}
}
}
class Consumer extends Thread{
private Resource rs;
public Consumer(Resource rs1) {
rs = rs1;
}
public void run() {
for(int i = 0 ; i < 5; i++) {
int value = rs.getValue();
System.out.println("Consumer -> Getting data= " + value);
try {
sleep(100);
}catch(Exception ex) {
ex.printStackTrace();
}
}
}
}
public class Dependent {
public static void main(String[] args) throws IOException {
Resource res = new Resource();
Producer p1 = new Producer(res);
Consumer c1 = new Consumer(res);
p1.start();
c1.start();
}
}
或
class Resource {
private static final int WAIT_VALUE = -1;
private volatile int value = WAIT_VALUE;
public synchronized void setValue(int val) {
while(value > WAIT_VALUE && value != val) {
try {
wait();
}catch(Exception ex) {}}
value = val;
notifyAll();
}
public synchronized int getValue() {
while(value == WAIT_VALUE) {
try {
wait();
}catch(Exception ex) {}}
int answer = value;
value = WAIT_VALUE;
notifyAll();
return answer;
}
}