Hallo,
ich habe ein Problem mit meinem Multithreading Programm beim parallelen Zugriff auf ein Objekt.
Ich habe ein Objekt namens Bus welcher eine ArrayList von Personen enthält.
Nun sollen Personen mit Hilfe von Threads parallel in den Bus eingefügt werden bis dieser komplett voll ist. Ist das erreicht sollen diese Threads terminieren und zwei oder mehr andere Threads wiederum den Bus komplett leeren und dann terminieren.
Allerdings habe ich bei ca 50% der Durchläufe das Problem, dass der Bus ständig kreuz und quer gefüllt und geleert wird weil ich scheinbar die synchronized Blöcke falsch verwende oder die Monitore.
Hier ist mein Ansatz:
Am liebsten wäre es mir natürlich wenn nach dem leeren wieder die Einfüge Threads benachrichtigt werden würden und der Bus sozusagen endlos komplett gefüllt und wieder komplett geleert wird. Aber erstmal will ich das Konzept dahinter verstehen.
PS: mir ist natürlich klar dass immer nur ein Thread zur selben Zeit auf das Object zugreifen darf.
ich habe ein Problem mit meinem Multithreading Programm beim parallelen Zugriff auf ein Objekt.
Ich habe ein Objekt namens Bus welcher eine ArrayList von Personen enthält.
Nun sollen Personen mit Hilfe von Threads parallel in den Bus eingefügt werden bis dieser komplett voll ist. Ist das erreicht sollen diese Threads terminieren und zwei oder mehr andere Threads wiederum den Bus komplett leeren und dann terminieren.
Allerdings habe ich bei ca 50% der Durchläufe das Problem, dass der Bus ständig kreuz und quer gefüllt und geleert wird weil ich scheinbar die synchronized Blöcke falsch verwende oder die Monitore.
Hier ist mein Ansatz:
Java:
public class Person {
private String name;
public Person(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
@Override
public String toString()
{
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
Java:
public class Bus {
private ArrayList<Person> places;
private int maxCapacity;
private int currentCapacity;
public Bus(int maxCapacity)
{
this.places = new ArrayList<>();
this.maxCapacity = maxCapacity;
this.currentCapacity = 0;
}
public boolean addPerson(Person person){
if(person != null && currentCapacity+1 <= maxCapacity){
places.add(person);
this.currentCapacity++;
return true;
}
return false;
}
public boolean removePerson(int position){
if(position < places.size() && position >= 0){
places.remove(position);
currentCapacity--;
return true;
}
return false;
}
public int getCurrentCapacity(){
return this.currentCapacity;
}
public int getMaxCapacity(){
return this.maxCapacity;
}
@Override
public String toString()
{
return "Bus{" +
"places=" + places +
", maxCapacity=" + maxCapacity +
", currentCapacity=" + currentCapacity +
'}';
}
}
Java:
public class AddPersonThread implements Runnable{
public static Object monitor = new Object();
private Bus bus;
public AddPersonThread(Bus bus)
{
this.bus = bus;
}
@Override
public void run()
{
while(true){
synchronized (AddPersonThread.monitor)
{
if (bus.addPerson(new Person("Hans")))
{
System.out.println(Thread.currentThread().getName() + " added a person! Bus: " + bus.getCurrentCapacity());
} else
{
System.out.println(Thread.currentThread().getName() + ": Bus is full");
synchronized (RemovePersonThread.monitor)
{
RemovePersonThread.monitor.notifyAll();
}
return;
}
}
}
}
}
Java:
public class RemovePersonThread implements Runnable {
public static final Object monitor = new Object();
private Bus bus;
public RemovePersonThread(Bus bus)
{
this.bus = bus;
}
@Override
public void run()
{
synchronized (RemovePersonThread.monitor){
try
{
RemovePersonThread.monitor.wait();
} catch (InterruptedException e)
{
e.printStackTrace();
}
while(bus.getCurrentCapacity() != 0){
bus.removePerson(0);
System.out.println(Thread.currentThread().getName() + " removed a person");
}
}
return;
}
}
Java:
public class Main {
public static void main(String[] args)
{
Bus bus = new Bus(5);
AddPersonThread addPersonThread = new AddPersonThread(bus);
Thread thread1 = new Thread(addPersonThread);
thread1.setName("Thread A: ");
AddPersonThread addPersonThread1 = new AddPersonThread(bus);
Thread thread2 = new Thread(addPersonThread1);
thread2.setName("Thread B: ");
RemovePersonThread removePersonThread = new RemovePersonThread(bus);
RemovePersonThread removePersonThread2 = new RemovePersonThread(bus);
Thread thread3 = new Thread(removePersonThread);
Thread thread4 = new Thread(removePersonThread2);
thread3.setName("Thread C: ");
thread4.setName("Thread D: ");
thread3.start();
thread4.start();
thread1.start();
thread2.start();
}
}
Am liebsten wäre es mir natürlich wenn nach dem leeren wieder die Einfüge Threads benachrichtigt werden würden und der Bus sozusagen endlos komplett gefüllt und wieder komplett geleert wird. Aber erstmal will ich das Konzept dahinter verstehen.
PS: mir ist natürlich klar dass immer nur ein Thread zur selben Zeit auf das Object zugreifen darf.
Zuletzt bearbeitet: