我正在努力理解我正在做的任务的部分并发性。我想我已经完成了基础知识,但是我已经陷入了我的用例的细微差别。
如果我还没有掌握这个问题的艺术,我会提前道歉。
基本理念:
我有一个类,其中一些对象被实例化为房屋部分的表示,它们唯一的主要功能是操作()。问题是,当“贝尔”运作时,我希望其他人等待()。我的while语句基于铃声切换(布尔值)。如果它打开 - 等待(),如果没有,继续。似乎在运行这个程序时,我为了“Bell”而挨饿其他螺纹对象。
关于我哪里出错了?
import java.util.ArrayList;
class Test extends Thread {
static int number = 0;
private static final int TIMES = 30;
private static boolean bellstatus = false;
private String name;
private int val;
Test(String y,int x) {
number = number +1;
val = x;
name = new String(y);
}
public void run() { // overrides default run()
for (int i=val; i>0; i--){
System.out.println(name+" run() : " + i);
operate();
}
}
public synchronized void operate(){
System.out.println(name+ " operating");
while(bellstatus){
try{
System.out.println("Bell is ringing");
wait();}catch(InterruptedException e){}
}
if(name.equals("Bell")){
try{
System.out.println("Bell working");
bellstatus = true;
Thread.sleep(500);
Thread.yield();}catch(InterruptedException e){}
bellstatus = false;
notifyAll();
System.err.println("Bell is done");
}
if(name.equals("Door")){
try{
System.out.println("Door working");
Thread.sleep(500);}catch(InterruptedException e){}
}
if(name.equals("Window")){
try{
System.out.println("Window working");
Thread.sleep(500);}catch(InterruptedException e){}
}
}
public static void main(String arg[]) {
ArrayList<Test> example = new ArrayList();
Test a = new Test("Bell",20);
Test b = new Test("Door",20);
Test c = new Test("Window",20);// create thread
example.add(a);
example.add(b);
example.add(c);
System.out.println("Number of objects: "+a.number);
for(int i = 0;i<example.size();i++)
example.get(i).start();
// start thread run
}
}
答案 0 :(得分:1)
只使用一个线程和一个runnables队列。只有一个线程的执行程序会将您的任务排队,直到完成一个任务https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executor.html
答案 1 :(得分:1)
请不要使用Raw Types(您可以使用钻石运营商<>
)。然后,如果我理解你的问题,一个可能的解决方案是使用ReentrantLock
之类的,
static class Test extends Thread {
static int number = 0;
private static Lock lock = new ReentrantLock();
private String name;
private int val;
Test(String y, int x) {
number = number + 1;
val = x;
name = new String(y);
}
public void run() {
for (int i = val; i > 0; i--) {
System.out.println(name + " run() : " + i);
operate();
}
}
public synchronized void operate() {
System.out.printf("%s operating%n", name);
lock.lock();
try {
System.out.printf("%s working%n", name);
Thread.sleep(500);
System.out.printf("%s done%n", name);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public static void main(String arg[]) {
List<Test> example = new ArrayList<>();
Test a = new Test("Bell", 20);
Test b = new Test("Door", 20);
Test c = new Test("Window", 20);// create thread
example.add(a);
example.add(b);
example.add(c);
System.out.println("Number of objects: " + a.number);
for (int i = 0; i < example.size(); i++) {
example.get(i).start();
}
// start thread run
}
答案 2 :(得分:0)
notifyAll
的javadoc提及:
唤醒等待此对象监视器的所有线程。线程通过调用其中一个wait方法等待对象的监视器。
但是operate
方法正在同步线程对象的实例。因此,notifyAll
不会唤醒正在等待的线程,因为每个线程拥有不同的监视器并且正在该监视器上等待。
解决此问题的一种方法是同步共享锁:
...
static Object lock = new Object();
...
public void operate() {
synchronized (lock) {
System.out.println(name + " operating");
while (bellstatus) {
try {
System.out.println("Bell is ringing");
lock.wait();
} catch (InterruptedException e) {
}
}
if (name.equals("Bell")) {
try {
System.out.println("Bell working");
bellstatus = true;
Thread.sleep(500);
Thread.yield();
} catch (InterruptedException e) {
}
bellstatus = false;
lock.notifyAll();
System.err.println("Bell is done");
}
if (name.equals("Door")) {
try {
System.out.println("Door working");
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
if (name.equals("Window")) {
try {
System.out.println("Window working");
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
}
}