我只是Java的初学者,偶然发现了多线程应用程序。我知道这个问题类似于这里的一些帖子,但我找不到更好的答案。基本上,我想将一个对象传递给一个静态方法,该方法只会根据对象的值/属性返回一个输出。对于每个调用,我正在创建一个对象的新实例,并且我无法以任何方式修改方法内的对象。现在,我的问题是,JVM是否会为多个线程的每次调用创建静态方法的新实例及其局部变量到堆栈中(不包括堆上的对象)?为了清楚地了解我想要实现的目标,这是我的代码:
TestConcurrent.java
import classes.Player;
public class TestConcurrent
{
private static int method(Player player)
{
int y = (player.getPoints() * 10) + 1;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
return ++y;
}
public static void main(String[] args) throws Exception
{
// Create 100 threads
for(int i=1;i<=100;i++)
{
final int j = i;
// Create a new Thread
new Thread()
{
public void run()
{
// Create a new instance of the Player class
Player player = new Player(j,j,"FirstName" + j, "LastName" + j);
// Call static method() and pass a new instance of Player class
System.out.println("Thread " + j + ": " + TestConcurrent.method(player));
// Check the values of the Player class after the call to the static method()
System.out.println("Player" + player.getAcctId() + " : Points=" + player.getPoints() + " Name=" + player.getFirstName() + " " + player.getLastName());
}
}.start();
}
}
}
Player.java
package classes;
public class Player
{
private int acctId, points;
String firstName, lastName;
public Player(int acctId, int points, String firstName, String lastName)
{
this.acctId = acctId;
this.points = points;
this.firstName = firstName;
this.lastName = lastName;
}
public int getAcctId() {
return acctId;
}
public void setAcctId(int acctId) {
this.acctId = acctId;
}
public int getPoints() {
return points;
}
public void setPoints(int points) {
this.points = points;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
输出:
由于我没有放置一个synchronized关键字,每次输出都会有所不同,它看起来类似于以下内容:(输出正确,这正是我所期待的,我只想澄清我在正确的路径,因为我不想使用同步,因为它会减慢进程,因为每个线程必须等待另一个线程完成才能调用静态方法)
Thread 2: 22
Player8 : Points=8 Name=FirstName8 LastName8
Thread 22: 222
Thread 26: 262
Thread 23: 232
Player23 : Points=23 Name=FirstName23 LastName23
Thread 21: 212
Player21 : Points=21 Name=FirstName21 LastName21
Thread 25: 252
Player25 : Points=25 Name=FirstName25 LastName25
Thread 20: 202
Thread 19: 192
Thread 24: 242
Player24 : Points=24 Name=FirstName24 LastName24
Player9 : Points=9 Name=FirstName9 LastName9
Thread 28: 282
答案 0 :(得分:4)
JVM会为多个线程的每次调用创建静态方法及其局部变量的新实例(不包括堆中的对象)吗?
是的,这是完全正确的。
如果静态方法仅引用局部变量,则它自动是线程安全的。 (事实上,这也适用于非静态方法。)
一般来说,我会说如果可能的话你应该避免static
。一般来说,由于静态成员在某种意义上是全局性的,因此代码更难以测试和推理。
答案 1 :(得分:4)
static
方法不是问题,只有static
个变量将在各个线程之间共享。
所以两个线程调用
public static int sum(int a, int b) {
int tmp = a + b;
return tmp;
}
不会遇到问题。
static int tmp;
public static int sum(int a, int b) {
tmp = a + b;
return tmp;
}
多线程失败,因为一个线程可能会覆盖其他tmp
值。
即使在static
方法中,局部变量仍然是局部的,因此是安全的。
使用static
方法很好。它强调该方法不需要访问对象变量。使用static
非常量变量容易出错,不惜一切代价避免这种情况(如果需要访问变量,则使用常量上的同步)。