我使用线程池创建了100个线程,增加了资金,并使用了同步,但是结果没有达到1000000。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPool {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(100);
for(int i=0;i<100;i++) {
Thread t=new MyThread();
pool.execute(t);
}
pool.shutdown();
}
}
class MyThread extends Thread{
private static int money=0;
@Override
public void run() {
addMoney();
}
public synchronized void addMoney() {
for(int i=0;i<10000;i++)
money+=1;
System.out.println(money);
}
}
答案 0 :(得分:1)
您添加到synchronized
方法中的addMoney
关键字使用this
作为内在锁。由于this
指向每个线程实例,并且每个线程仅调用一次此方法,因此没有效果。
要在线程之间同步访问,可以显式指定全局锁实例,例如ThreadPool
类:
public void addMoney() {
synchronized(ThreadPool.class) {
for(int i=0;i<10000;i++)
money+=1;
System.out.println(money);
}
}
通过将addMoney
方法声明为static
,可以实现几乎相同的效果。在这种情况下,内部锁将改为MyThread
类:
public static synchronized void addMoney() {
for(int i=0;i<10000;i++)
money+=1;
System.out.println(money);
}
您可以在Java文档https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
中找到更多详细信息。答案 1 :(得分:0)
问题是访问和更新共享静态变量时,每个任务都在不同的对象上同步。这意味着工作线程之间没有相互排斥。这意味着您的应用程序计算出的值可能是不可预测的和/或特定于平台的。 (除非你很幸运...)
一种解决方法是将addMoney
更改为static synchronized
方法。这将导致线程在MyThread.class
对象上同步。但是,如果执行此操作,则会发现您的应用程序是有效单线程...因为只有您的MyThread
实例之一才能执行其addMoney
方法一次。
目前尚不清楚正确的解决方法是什么,因为尚不清楚此“玩具”示例试图演示什么。但是我提到的替代方法至少应该可靠地计算结果。
您不应该扩展Thread
。您的MyThread
类应替换为实现Runnable
的类。您在这里所做的是使用Thread
对象,就好像它只是一个Runnable
。那是个坏主意。您使用的ExecutorService
将负责线程的创建。您需要为它提供“任务”而不是“线程”。