Java多线程:如何防止两个线程同时复制逻辑?

问题描述 投票:0回答:1

我创建了一个 Fish 类,它模拟在 Java 程序中繁殖的鱼。每条鱼必须通过遇到另一条随机鱼来繁殖。但问题是两条鱼作为一对找到彼此并同时生出两个孩子。这个繁殖过程同时重复多次。

我在水族馆课上养鱼。鱼出生后,达到繁殖年龄(即应从4岁开始)后,它应该从水族类中随机寻找配偶。但在我编写的代码中,一条鱼想要寻找配偶并繁殖,此时,该鱼也通过选择 Aquarium 类中的第一条鱼来繁殖。两条鱼会在海的一处诞生。事实上,应该诞生一条鱼。我不知道如何解决这个问题。真正的问题在于繁殖方法。在哪里以及如何写。请建议我最佳解决方案。先谢谢大家的回复了。

我有一个鱼课:

package lesson.uz;

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;

import java.util.Random;

@Getter
@Setter
@EqualsAndHashCode
public class Fish extends Thread {

    private long id;
    private Gender gender;
    private Integer lifespan;
    private String fishName;
    private Integer age = 0;
    private static Long counter = 1L;

    public Fish(Gender gender) {
        this.gender = gender;
        this.lifespan = new Random().nextInt(11)+40;
        this.fishName = "Fish"+ counter++;
        this.id = Math.abs(new Random().nextLong() * System.currentTimeMillis());
        System.out.println(fishName + " created. "+System.currentTimeMillis());
    }

    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(1000);
                reproduce();
                age++;
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

    }

    public void reproduce() {
        Fish randomFish = getRandomFish();
        long count = Aquarium.raddom.stream().filter(id -> randomFish.getId() == id || this.getId() == id).count();

        if (count == 0 && this.age >= 4 && randomFish.getAge() >= 4 && this.getGender() != randomFish.getGender()) {

            Aquarium.raddom.add(this.id);
            Aquarium.raddom.add(randomFish.id);

            System.out.println(this.fishName + " and " + randomFish.getFishName() + " meet.\n");
            Fish babyFish = createFish();
            Aquarium.fishList.add(babyFish);
            Aquarium.raddom.remove(this.id);
            Aquarium.raddom.remove(randomFish.id);
        }
    }

    public static Fish createFish() {
        Fish newFish = new Fish(Math.random() > 0.5 ? Gender.MALE : Gender.FEMALE);
        newFish.start();
        return newFish;
    }

    public Fish getRandomFish() {
        int randomNum = 0;
        Fish currenFish = null;
        while (true) {
            randomNum = new Random().nextInt(Aquarium.fishList.size());
            currenFish = Aquarium.fishList.get(randomNum);

            if (this != currenFish) {
                break;
            }
        }
        return currenFish;
    }
}

我有水族馆课:

package lesson.uz;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Aquarium extends Thread {

    public static List<Fish> fishList = new ArrayList<>();
    public static List<Long> raddom = new ArrayList<>();

    @Override
    public void run() {
        
    }
}

和主类:

package lesson.uz;

public class Main {

    public static void main(String[] args) {
        Aquarium aquarium = new Aquarium();
        aquarium.start();
        init();
    }

    public static void init() {
        Fish fish1 = new Fish(Gender.MALE);
        fish1.start();
        Aquarium.fishList.add(fish1);
        Fish fish2 = new Fish(Gender.FEMALE);
        fish2.start();
        Aquarium.fishList.add(fish2);
    }
}

问题(问题): 鱼A和鱼B互相选择作为配偶。 与此同时,鱼B也选择了鱼A,并开始并行的繁殖过程。 结果,同时创建了两个孩子。

问题: 如何解决这个问题呢?如何确保复制过程一次只发生一次?

public static List<Long> raddom = new ArrayList<>();

我尝试通过添加 raddom(产房意义上的)列表来解决问题。我的程序还没有完成。但这没有帮助。请给我建议最佳解决方案。

java multithreading concurrency synchronization thread-safety
1个回答
0
投票

高水平

我将从 Fish 类中删除繁殖方法并将其放置在 Aquarium 类中。当鱼足够大可以繁殖时,它会调用水族馆的繁殖方法。水族馆会将鱼添加到列表中,如果列表中至少有两条鱼,则删除它们,并创建一条新鱼。 (可能有更好的方法来实现这一点,但它会起作用。)

我还建议将

new ArrayList<>();
更改为
Collections.synchronizedList(new ArrayList<>())

© www.soinside.com 2019 - 2024. All rights reserved.