我创建了两个单独的线程,一个用于写入列表,另一个用于从列表中删除。
package com.produ.consu;
public class Test {
public static void main(String[] args) {
Operations operations = new Operations();
Runnable r1 = new ThreadsClass(operations);
Runnable r2 = new ThreadsClass(operations);
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.setName("READ");
t2.setName("WRITE");
t1.start();
t2.start();
}
}
以上是我在其中创建线程的Test类。
package com.produ.consu;
public class ThreadsClass implements Runnable {
Operations operations;
ThreadsClass(Operations operations){
this.operations=operations;
}
@Override
public void run() {
// TODO Auto-generated method stub
if(Thread.currentThread().getName().equals("WRITE")) {
operations.writeList();
}
else {
operations.readList();
}
}
}
以上是基于线程名称调用同步方法的类:
import java.util.ArrayList;
import java.util.List;
public class Operations {
List<Integer> list=null;
int count=0;
boolean flag;
Operations(){
list=new ArrayList<>();
flag=true;
}
public synchronized void writeList() {
// TODO Auto-generated method stub
while(true) {
if(flag) {
count++;
list.add(count);
System.out.println("inise if block...."+Thread.currentThread().getName());
System.out.println(list);
flag=false;
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else {
notify();
}
}
}
public synchronized void readList() {
// TODO Auto-generated method stub
while(true) {
if(!flag) {
Integer i = list.remove(0);
System.out.println(i+"..removed at index by"+Thread.currentThread().getName());
flag=true;
notify();
}
else {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
上面是我提到的功能。 因此,写线程不必将元素写到列表中,直到第二个线程将其删除为止。 一旦删除,第二则应通知1st并等待直到元素插入。 但是得到...
表示是否受阻。...WRITE [1]
甚至没有删除,它必须是一个连续的过程。 给我有关给定代码的建议。
答案 0 :(得分:1)
您还应该在wait()
块内else
,否则,如果while
不满意并且另一个线程无法获得if
,则notify
将继续运行机会执行。
执行读/写操作后,线程应调用 public synchronized void writeList() {
while (true) {
if (flag) {
count++;
list.add(count);
System.out.println("inise if block...." + Thread.currentThread().getName());
System.out.println(list);
flag = false;
try {
notify(); //notify the read thread that write is complete
wait(); // go into the waiting state so that no further write is done until the current element is removed by the read thread.
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
try {
wait(); //wait in else, otherwise while will run endlessly
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public synchronized void readList() {
while (true) {
System.out.println("in read");
if (!flag) {
Integer i = list.remove(0);
System.out.println(i + "..removed at index by" + Thread.currentThread().getName());
flag = true;
try {
notify(); //notify write thread that read is complete
wait(); //go into wait until new element is inserted
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
try {
wait(); //wait in else otherwise while runs endlessly
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
来唤醒另一个线程,并且其本身应进入等待状态。
{{1}}
答案 1 :(得分:0)
您应该将方法同步替换为更精细的同步:用一个同步块包装访问列表和更新计数的操作。
或者,使用链接的阻塞队列在线程之间传递“消息”(或者,在更高级的方案中,使用Akka,Kafka,zeromq等消息传递解决方案或其他类似解决方案)
答案 2 :(得分:0)
由于一次只能添加一个要素,因此也可以使用交换器。 看看Java并发包。
import java.io.IOException;
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class Foo {
public static void main(String[] args) throws IOException, InterruptedException {
final Exchanger<Integer> exchanger = new Exchanger<>();
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(() -> {
// producer
int count = 0;
while (!Thread.currentThread().isInterrupted()) {
try {
exchanger.exchange(count++);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
executorService.execute(() -> {
// reader
while (!Thread.currentThread().isInterrupted()) {
try {
System.out.println("consume " + exchanger.exchange(null));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
System.in.read();
executorService.shutdownNow();
executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("Shut down");
}
}