我可能早先问过here,而且缺乏理解和复杂,现在我以更容易理解的方式重写程序。
问题:
当我运行2个线程时,只有1个线程完成这项工作。
怀疑助手
我怀疑线程自己锁定,因此另一个线程无法访问它。
代码
初始化主要
Shop shop = new Shop();
CarGenerator carGenerator = new CarGenerator(shop);
Mechanics mechanics1 = new Mechanics(shop, "Mechanics 1");
Mechanics mechanics2 = new Mechanics(shop, "Mechanics 2");
//Threads
Thread CarThread = new Thread(carGenerator);
Thread Mechanics1Thread = new Thread(mechanics1);
Thread Mechanics2Thread = new Thread(mechanics2);
CarThread.start();
Mechanics1Thread.start();
Mechanics2Thread.start();
在这里,我们可以看到2个线程正在创建并按预期工作。
现在机械师的功能是什么:
@Override
public void run() {
while (true) {
System.out.println("Working Thread: " + Thread.currentThread().getName());
shop.CarFix(MechanicsName);
}
}
线索:
这里我打印出有多少个线程,结果是2:
Working Thread: Thread-1
Working Thread: Thread-2
很好,现在两个线程都按预期运行,现在我将在商店工作无限。我不会削减以显示整个过程并更好地理解:
public void CarFix(String MechanicsName) {
Car car;
synchronized (ListCarEntry) {
while (ListCarEntry.size() == 0) {
try {
ListCarEntry.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
Logger.getLogger(Shop.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("Working Thread: " + Thread.currentThread().getName());
//Done 2 Sec Fixing
//Release Now
car = (Car) ((LinkedList<?>) ListCarEntry).poll();
((LinkedList<Car>) ListCarFix).offer(car);
System.out.println("Car FIX: " + car.getCarName() + " being fixed by " + MechanicsName);
}
这里Thread只运行一个而不是之前的2个线程,结果是:
Working Thread: Thread-1
Car FIX: Car 1 being fixed by Mechanics 1
Working Thread: Thread-1
Car FIX: Car 2 being fixed by Mechanics 1
Working Thread: Thread-1
Car FIX: Car 3 being fixed by Mechanics 1
现在只有力学1修复,而力学2缺失。
线索2:
当我尝试删除SACEP FOR 2 SEC 时,结果就是我真正想要的结果:
Working Thread: Thread-1
Car FIX: Car 1 being fixed by Mechanics 1
Working Thread: Thread-2
Car FIX: Car 2 being fixed by Mechanics 2
Working Thread: Thread-1
Car FIX: Car 3 being fixed by Mechanics 1
这是我真正想要看到的。
问题:
如何确保线程按预期工作并具有睡眠功能?
对于直到最后阅读的人:
看到我不知道删除睡眠可能会解决问题,安静怪异..无论如何任何想法的人..并抱歉长期的问题。
修改
这是我的CarGenerator课程:
public class CarGenerator implements Runnable{
Shop shop;
public CarGenerator(Shop shop) {
this.shop = shop;
}
@Override
public void run() {
int i = 0;
while (true) {
i++;
Car car = new Car(shop, "Car " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(CarGenerator.class.getName()).log(Level.SEVERE, null, ex);
}
Thread thCar = new Thread(car);
thCar.start();
}
}
}
这个叫这个车的车把车开到车间:
public class Car implements Runnable{
private String CarName;
private Shop shop;
public Car(Shop shop, String CarName) {
this.shop = shop;
this.CarName = CarName;
}
public String getCarName() {
return CarName;
}
@Override
public void run() {
//DO
synchronized(this) {
shop.CarEntrance(this);
}
}
}
这是汽车进入商店的地方
public void CarEntrance(Car car) {
System.out.println("Entry: " + car.getCarName());
if (ListCarEntry.size() == 10){
System.out.println("Exit: " + car.getCarName() + "Exit the store, cause FULL");
return;
}
((LinkedList<Car>) ListCarEntry).offer(car);
if (ListCarEntry.size() == 1) {
synchronized(ListCarEntry) {
ListCarEntry.notify();
}
}
}
如此处所示,我呼叫通知同步通知机械师正在等待车辆等待车辆进入。
答案 0 :(得分:1)
这是一个非常奇怪的设置。您的机制是同步的线程,但同步是在Shop中完成的;你通常在线程本身同步。而且,如果您使用线程安全队列对象来管理要修复的汽车,那么您真的不需要显式同步。这使得它成为典型的生产者/消费者问题,商店是生产者,机械师是消费者。
class Shop {
private static BlockingQueue<Integer> cars = new ArrayBlockingQueue<>();
private static int carNumber;
private static Random RANDOM = new Random();
public static void main(String[] args) {
// you can add more mechanics here
int mechanicsCount = 2;
for (int i = 0; i < mechanicsCount; i++) {
new Thread(createMechanic(String.format("Mechanic %d", i))).start();
}
ScheduledExecutorService producingScheduler = Executors.newSingleThreadScheduledExecutor();
// add a new car every 300 ms
producingScheduler.scheduleAtFixedRate(() -> {
try {
cars.put(carNumber++);
} catch (InterruptedException e) { }
}, 0, 300, TimeUnit.MILLISECONDS);
}
// the concurrently running code
private Runnable createMechanic(String name) {
return () -> {
try {
while (true) {
// synchronization happens here: queue is thread-safe
Integer car = cars.take();
System.out.printf("repairing car %s in thread %s\n", car, Thread.currentThread().getName());
// take some time repairing
int timeToRepair = RANDOM.nextInt(500);
Thread.sleep(timeToRepair);
System.out.printf("car %s is repaired, took %s ms\n", car, timeToRepair);
}
} catch (InterruptedException e) { }
};
}
}
这样,机械师将在队列中等待下一辆车出现。
答案 1 :(得分:0)
对于解决方案,我只是从 CarFix函数移动了Thread.sleep:
public void CarFix(String MechanicsName) {
Car car;
synchronized (ListCarEntry) {
while (ListCarEntry.size() == 0) {
try {
ListCarEntry.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//There is No Sleep
car = (Car) ((LinkedList<?>) ListCarEntry).poll();
((LinkedList<Car>) ListCarFix).offer(car);
System.out.println("Car FIX: " + car.getCarName() + " being fixed by " + MechanicsName);
}
并将其移至力学课程:
@Override
public void run() {
while (true) {
try {
Thread.sleep(3000);
} catch (InterruptedException ex) {
Logger.getLogger(Shop.class.getName()).log(Level.SEVERE, null, ex);
}
shop.CarFix(MechanicsName);
}
}
结果:
Entry: Car 1
Entry: Car 2
Working Thread: Thread-1
Working Thread: Thread-2
Car FIX: Car 1 being fixed by Mechanics 2
Car FIX: Car 2 being fixed by Mechanics 1
Entry: Car 3
Entry: Car 4
Entry: Car 5
Working Thread: Thread-1
Working Thread: Thread-2
Car FIX: Car 3 being fixed by Mechanics 1
Car FIX: Car 4 being fixed by Mechanics 2
我认为这辆车是2乘2的车,我真的不想要,我想要一个独立的力学,所以我试着将Cargenerator设置为10秒进行调试测试,结果:
Entry: Car 1
Working Thread: Thread-2
Car FIX: Car 1 being fixed by Mechanics 2
Entry: Car 2
Working Thread: Thread-1
Car FIX: Car 2 being fixed by Mechanics 1
Entry: Car 3
Working Thread: Thread-2
Car FIX: Car 3 being fixed by Mechanics 2
Entry: Car 4
Working Thread: Thread-1
Car FIX: Car 4 being fixed by Mechanics 1
现在这很公平,效果比预期好得多。
感谢所有的贡献,案例已关闭。