【问题标题】:Java Create Two Threads but Only One RunningJava 创建两个线程但只有一个正在运行
【发布时间】:2018-04-18 12:39:01
【问题描述】:

我之前可能问过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);

}

这里只有一个线程在运行,而不是之前的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

目前只修复了 Mechanics 1,而 Mechanics 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 类:

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();
        }

    }
}

如此处所示,我调用 notify Synchronized 通知,由机械师调用,等待更早等待汽车进入。

【问题讨论】:

    标签: java multithreading concurrency synchronized


    【解决方案1】:

    一开始这是一个非常奇怪的设置。您的机制是正在同步的线程,但同步是在商店中完成的;您通常会在线程本身中同步。更重要的是,如果您使用线程安全队列对象来管理要修复的汽车,您实际上并不需要显式同步。这使它成为一个典型的生产者/消费者问题,商店是生产者,机械师是消费者。

    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) { }
            };
    
        }
    }
    

    这样,机械师将在队列中等待下一辆车出现。

    【讨论】:

    • 嗨,感谢您的回复,老实说,我使用同步,以便我可以利用等待和通知,如果没有,它将显示 MonitorException。我想使用等待和通知来创建一个队列系统。所以我应该在调用 carfix 之前将同步放在 Mechanics 类中?我刚试过把同步放在力学里面,结果还是一样..
    • 重点是我仍然需要通知等待功能,这样我就可以拥有一个队列系统。并想创建一个生产者/消费者,Car 成为生产者(因为我生成了汽车),而 Mechanics 需要修复(消费汽车)。它对一种机制很有效,因为它变成了两种机制就变得不公平了
    • @JoesLie 等待/通知不是一个好的机制(更不用说你没有发布调用notify() 的代码)。原因是notify() 可能会在机制调用wait() 之前被调用,这将导致机制等待下一次调用notify()。与低级同步相比,研究 Java 提供的并发支持确实更好。
    • 检查编辑,我已经调用了等待函数的通知。
    • 好的,我已将睡眠从 CarFix 功能更改为个人机械,它以某种方式工作。 2乘2,它清除了汽车。所以这就是解决方案,非常奇怪的测试。无论如何,谢谢大家,祝你有美好的一天
    【解决方案2】:

    对于解决方案,我只是将 Thread.sleep 从 CarFix Function 中移出:

    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
    

    现在它很公平,并且比预期的要好得多。

    感谢您的所有贡献,并且案件已结案

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多