同时启动线程并争论全局变量

Start Threads same time and dispute global variables

我正在尝试了解如何实现有争议的全局变量的线程。在我的实现中,我创建了 2 个变量,我想要 4 个线程(例如)通过递减来争论它。

第一个问题是我实现消费的方式总是遵循一个顺序(第一个线程减少片状冰淇淋,第二个线程减少巧克力冰淇淋)。

有什么办法可以改进这个规则吗?

而且我不想知道使用 CountDownLatch 的最佳位置

public class IceCream implements Runnable {

    private static int flake = 1;
    private static int chocolate = 1;
    @Override
    public void run() {
        buyIceCream();
        
    }   
    
    private void synchronized buyIceCream() {
try {
            
            if(IceCream.flake>0) {
                System.out.println("");
                System.out.println("successfully purchased " +Thread.currentThread().getName());
                Thread.sleep(200);
                IceCream.flake--;
                System.out.println("");             
            }
            else if(IceCream.chocolate>0) {
                System.out.println("");
                System.out.println("successfully purchased " +Thread.currentThread().getName());
                Thread.sleep(200);
                IceCream.chocolate--;
                System.out.println(""); 
            }
            else {
                System.out.println("No more ice cream " +Thread.currentThread().getName());
            }
        }
            catch(Exception e) {
                
            }       
        
    }
}
public static void main(String[] args) throws InterruptedException {
            IceCream c = new IceCream();
            Thread[] t = new Thread[4]; 
            for(int i = 0; i<t.length; i++) {
                t[i] = new Thread(c);
                t[i].setName("Kid"+ i);
                t[i].start();
                t[i].join();
                
            }
    
        }

这是一个错误:

t[i].start();
t[i].join();

在线程结束之前,join() 调用不会 return,因此您的程序永远不会允许多个线程同时 运行。您可以通过编写两个单独的循环来修复错误。第一个创建并启动所有线程,然后第二个加入所有线程。

for(int i = 0; i<t.length; i++) {
    t[i] = new Thread(c);
    t[i].setName("Kid"+ i);
    t[i].start();
}
for(int i = 0; i<t.length; i++) {
    t[i].join();    
}

这是另一个错误:

public void run() {
    buyIceCream();
}   
    
private void synchronized buyIceCream() {
    ...
}

将一个线程所做的一切都包装在一个 synchronized 方法中是另一种确保不允许两个线程同时 运行 的方法。

至少,您应该从 synchronized 块中删除 sleep() 调用:

private void buyIceCream() {
    String message = "No more ice cream ";
    synchronized (this) {
        if(IceCream.flake>0) {
            IceCream.flake--;
            message = "Ice cream flake purchased by" + Thread.currentThread().getName();
        }
        else if(IceCream.chocolate>0) {
            IceCream.chocolate--;
            message = "Chocolate ice cream purchased by" + Thread.currentThread().getName();
        }
    }
    System.out.println(message);
    try {
        Thread.sleep(200);
    }
    catch(Exception e) {
        System.out.println("Never, EVER, completely ignore an exception.");
    }       
}

我也将 System.out.println() 调用移出了 synchronized 块,因为我知道任何 single 调用打印的字符都不会与由来自不同线程的单个调用打印的字符。 (参见 )