首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java MultiThreading任务,三个吸烟者和一个代理

Java MultiThreading任务,三个吸烟者和一个代理
EN

Stack Overflow用户
提问于 2021-12-05 14:33:23
回答 2查看 133关注 0票数 1

该任务由三个吸烟者组成,分别是三个线程和一个名为Agent的类,Agent具有三个属性:烟草打火机纸张

吸烟者只有其中一项,agent类应该将两项随机放在桌子上,然后吸烟者应该检查他们是否遗漏了这两项,然后捡起来,这样他们就可以用来吸烟了。

我有一个问题,我的产出有点奇怪,吸烟者倾向于同时挑选他们丢失的所有物品,尽管我认为我认为他们是不允许这样做的。

主班

代码语言:javascript
复制
public class Main {

    public static void main(String[] args) {
        Agent a = new Agent();
        
        Pusac p1 = new Pusac(0,a,"Paper");
        Pusac p2 = new Pusac(1,a,"Tobacco");
        Pusac p3 = new Pusac(2,a,"Lighters");

        p1.start();
        p2.start();
        p3.start();
    }

}  

我使用构造函数创建一个代理,并将其传递给smokers.Each烟雾器的构造函数,其中包含一个项、ID和代理。

烟民等级

代码语言:javascript
复制
public class Pusac extends Thread {

    int id;
    Agent a;
    String owns;
    
    public Pusac(int id, Agent a, String owns) {
        this.id = id;
        this.a = a;
        this.owns = owns;
    }
    
    @Override
    public void run() {
        while(true) {
        a.putTable();
        if(this.owns.equals("Paper") && a.tobacco == true && a.lighters == true){
                System.out.println("Smoker with ID " + this.id + " took tobacco and lighters.");
                a.smoke();
        } else if(this.owns.equals("Tobacco") && a.lighters == true && a.paper == true) {
                System.out.println("Smoker with ID " + this.id + " took lighters and paper.");
                a.smoke();
        } else if(this.owns.equals("Lighters") && a.paper == true && a.tobacco == true) {
                System.out.println("Smoker with ID " + this.id + " took paper and tobacco.");
                a.smoke();
        }
        }
    }
    
}

在烟雾器类函数中,我检查该代理是否具有当前线程冒烟器所需的项,然后调用agent类中的函数。

代理类

代码语言:javascript
复制
public class Agent {

    boolean paper;
    boolean tobacco;
    boolean lighters;
    
    
    public  void putTable() {
        Random random = new Random();
        int randomNumOne = random.nextInt(3);
        
        switch(randomNumOne) {
        case 0:
            paper = true;
        case 1: 
            tobacco = true;
        case 2:
            lighters = true;
        }
        
        int randomNumTwo = random.nextInt(3);
        
        if(paper!=true && randomNumTwo==0) {
            paper = true;
        } else if(tobacco!=true && randomNumTwo == 1) {
            tobacco = true;
        } else if(lighters != true && randomNumTwo == 2) {
            lighters = true;
        }
    }
    
    public synchronized void smoke() {
        System.out.println("Smoker with ID " + ((Pusac)Thread.currentThread()).id + " is smoking.");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        if(((Pusac)Thread.currentThread()).owns.equals("Paper")) {
            this.tobacco = false;
            this.lighters = false;
            System.out.println("Smoker with ID " + ((Pusac)Thread.currentThread()).id + " put down tobacco and lighters.");
        } else if(((Pusac)Thread.currentThread()).owns.equals("Tobacco")) {
            this.paper =false;
            this.lighters =false;
            System.out.println("Smoker with ID " + ((Pusac)Thread.currentThread()).id + " put down paper and lighters.");
        } else if (((Pusac)Thread.currentThread()).owns.equals("Lighters")) {
            this.tobacco =false;
            this.paper =false;
            System.out.println("Smoker with ID " + ((Pusac)Thread.currentThread()).id + " put down paper and tobacco.");
        }
        
  }
}

最后一个名为代理的类由一个函数组成,该函数将两个项随机放置在表中,项是布尔,然后我有函数烟雾,它只检查哪个吸烟者正在吸烟,然后将所有内容设置为false

我得到的输出

代码语言:javascript
复制
Smoker with ID 2 took paper and tobacco.
Smoker with ID 1 took lighters and paper.
Smoker with ID 0 took tobacco and lighters.
Smoker with ID 2 is smoking.
Smoker with ID 2 put down paper and tobacco.
Smoker with ID 2 took paper and tobacco.
Smoker with ID 0 is smoking.
Smoker with ID 0 put down tobacco and lighters.
Smoker with ID 0 took tobacco and lighters.
Smoker with ID 1 is smoking.

这是错误的,因为在现实中,只有一个人应该一次挑选一些东西,然后吸烟,以便其他人也可以拥有它。

衷心感谢您的帮助。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-12-05 14:51:35

,这是错误的,因为在现实中,只有一个人应该一次挑选一些东西,然后吸烟,这样其他人也可以拥有它。

因为您的Pusac线程类run方法不受任何人保护,所以您需要使用用于锁定smoke方法的相同监视器来使用run代码块。您可以通过synchronizing来尝试smokerun方法。

代码语言:javascript
复制
public void smoke() {
    synchronized(Agent.class) {
        ......
    }
}

@Override
public void run() {
    while(true) {
        synchronized(Agent.class) {
            ......
        }
    }
}
票数 1
EN

Stack Overflow用户

发布于 2021-12-05 14:58:05

在线程之间共享可变变量时,必须以不同的方式处理这些变量,否则每个读取线程可能会看到不同的值。

tldr:

修复现有程序的最简单方法很可能是定义所有“易失性”变量,如

代码语言:javascript
复制
volatile boolean paper;
volatile boolean tobacco;
volatile boolean lighters;

更长的解释是:出于性能原因,线程可能不会通过(缓慢) RAM访问来读取变量,而是从缓存中获取它们。只要相同的线程读取和写入变量,但当您试图在一个线程中设置值并从另一个线程读取它时,此操作就会失败。读取线程可能仍然会看到旧的值。

修复该问题的一种方法是声明变量易失性。这基本上指示要始终从RAM中读取值--对于这样大小的项目来说,这不应该有太大的区别。

您也可以使用java.util.concurrent.atomic.AtomicBoolean,而不是原始布尔值,这对于这个用例来说应该是一样的。

解决此问题的另一种方法是确保变量上的所有写更改都在同步块内。这样,开销就在写过程上,而不再在读者身上了。

然而,随着线程安全成为一个快速深入的话题,如果您计划做更多这样的多线程应用程序,就有一些关于这个主题的广泛阅读材料;-)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70235350

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档