Java 创建两个线程但只有一个 运行
Java Create Two Threads but Only One Running
我之前可能问过,缺乏理解和复杂,现在我以更容易理解的方式重写程序。
问题:
当我 运行 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
太好了,现在两个线程 运行ning 正如预期的那样,现在我将无限期地在商店工作。我不会切来展示整个过程并更好地理解:
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只有一个运行ning而不是之前的2个thread,结果是:
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:
当我尝试REMOVE THE SLEEP 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 Class:
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();
}
}
}
哪位叫这辆车class把车搬进店里:
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();
}
}
}
看到这里我调用了notify同步notify被机械师调用wait earlier等待进车
这是一个非常奇怪的开始设置。您的机制是被同步的线程,但同步是在商店中完成的;您通常会在线程本身中同步。更重要的是,如果您使用线程安全的队列对象来管理要修理的汽车,您实际上并不需要显式同步。这使它成为一个典型的 producer/consumer 问题,商店是生产者,机械师是消费者。
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) { }
};
}
}
这样,机械师就会排队等候下一辆车的出现。
对于解决方案,我只是从 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);
}
并将其移至 力学 Class:
@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
现在公平多了,效果比预期的好很多。
感谢大家的贡献,案件已结案。
我之前可能问过
问题:
当我 运行 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
太好了,现在两个线程 运行ning 正如预期的那样,现在我将无限期地在商店工作。我不会切来展示整个过程并更好地理解:
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只有一个运行ning而不是之前的2个thread,结果是:
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:
当我尝试REMOVE THE SLEEP 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 Class:
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();
}
}
}
哪位叫这辆车class把车搬进店里:
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();
}
}
}
看到这里我调用了notify同步notify被机械师调用wait earlier等待进车
这是一个非常奇怪的开始设置。您的机制是被同步的线程,但同步是在商店中完成的;您通常会在线程本身中同步。更重要的是,如果您使用线程安全的队列对象来管理要修理的汽车,您实际上并不需要显式同步。这使它成为一个典型的 producer/consumer 问题,商店是生产者,机械师是消费者。
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) { }
};
}
}
这样,机械师就会排队等候下一辆车的出现。
对于解决方案,我只是从 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);
}
并将其移至 力学 Class:
@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
现在公平多了,效果比预期的好很多。
感谢大家的贡献,案件已结案。