同时启动线程并争论全局变量
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 调用打印的字符都不会与由来自不同线程的单个调用打印的字符。 (参见 )
我正在尝试了解如何实现有争议的全局变量的线程。在我的实现中,我创建了 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 调用打印的字符都不会与由来自不同线程的单个调用打印的字符。 (参见 )