Java 同步方法到底做什么?
我正在使用Swing创建一个游戏。我使Java 同步方法到底做什么?,java,methods,synchronized,runnable,Java,Methods,Synchronized,Runnable,我正在使用Swing创建一个游戏。我使start()和stop()同步,因为有人告诉我这样更好。synchronized做什么?使用它的优势是什么 我的代码: import java.awt.Canvas; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.image.BufferStrategy; import java.awt.image.BufferedIm
start()
和stop()
同步,因为有人告诉我这样更好。synchronized做什么?使用它的优势是什么
我的代码:
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import javax.swing.JFrame;
public class SpritePractice extends Canvas implements Runnable{
private JFrame frame;
private final static int WIDTH = 200, HEIGHT = 200;
private final static int SCALE = 2;
private final static Dimension dimens= new Dimension(WIDTH*SCALE, HEIGHT*SCALE);
private BufferedImage image;
private Graphics g;
private long nanoSecond = 1000000000;
private double tick = nanoSecond/60;
private boolean running = false;
private int pixelsFromImage[];
private int pixel[][];
private static DateFormat dateFormat = new SimpleDateFormat("[" + "yyyy/MM/dd HH:mm:ss"
+"]");
private static DateFormat dateFormat2 = new SimpleDateFormat("[" + "HH:mm:ss" + "]");
public SpritePractice()
{
frame = new JFrame("Bomberman");
frame.setSize(dimens);
frame.setMinimumSize(dimens);
frame.setMaximumSize(dimens);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(this);
frame.pack();
frame.setVisible(true);
init();
}
public void init()
{
long startTime = System.nanoTime();
Calendar cal = Calendar.getInstance();
System.out.println("START: " + dateFormat.format(cal.getTime()));
start();
}
public void run()
{
long now = System.nanoTime();
long lastTick = System.nanoTime();
long lastSecond = System.nanoTime();
int frames = 0;
while(running)
{
now = System.nanoTime();
Calendar cal = Calendar.getInstance();
if(now-lastTick >= tick)
{
lastTick = now;
tick();
render();
frames++;
}
if(now-lastSecond >= nanoSecond)
{
lastSecond = now;
System.out.println(dateFormat2.format(cal.getTime()) + "FPS: " + frames);
frames = 0;
}
}
}
public void tick()
{
//updates values
}
public void render()
{
BufferStrategy bs = getBufferStrategy();
if(bs==null)
{
createBufferStrategy(2);
return;
}
Graphics g = bs.getDrawGraphics();
g.fillRect(0, 0, WIDTH*2, HEIGHT*2);
g.dispose();
bs.show();
//renders graphics
}
public synchronized void start()
{
running = true;
run();
}
public synchronized void stop()
{
running = false;
}
public static void main(String[] args)
{
new SpritePractice();
}
}Synchronized允许正确的线程处理,通过这种方式,Java将创建一个队列并处理应用程序中可能跨越的不同线程,而无需担心。在调用finished之前,您不能运行
stop()
方法。反之亦然synchronized
关键字在调用的同时对start()
和stop()
方法中没有两个线程进行求积
换句话说,当您按下start()按钮时,在启动完成之前,不允许按下stop()按钮。Java中的每个对象实例都有一个隐式互斥锁。方法上的同步相当于以下代码:
synchronized void foo() {
// Some code here
}
void foo() {
synchronized(this) {
// Same code here
}
}
净效果是,当两个线程试图同时执行该代码块时,一个线程在“synchronized”语句处等待,直到另一个线程从该块中出现。这确保了“此处代码”部分一次只在一个线程上运行。进入同步方法的线程将获得拥有该方法的整个对象的锁 在您的特定情况下,可以确保不会有两个并发线程同时执行
start()
和stop()
阅读有关同步方法的更多信息
e、 g.如果一个线程进入start()
方法,它将在另一个线程进入stop()
方法之前完成其执行。如果不同步这两种方法,则可能出现以下顺序:
--线程1进入start()
--线程1将布尔字段设置为
true
--线程2进入
stop()
--线程2将
boolean
字段设置为false
--线程1执行
run()
方法这是你绝对不想要的。既然没有人用简单的英语解释过,我会: 将方法标记为“synchronized”意味着您不希望多个线程同时访问该方法。如果你不想让你的代码允许所谓的“竞争条件”,这是很有用的——同样用简单的英语来说——“无论哪个线程先到达这里,都会赢” 下面是一个例子: 想象一下,一个简单的银行应用程序可以重新提取和存款。如果你有三个线程运行-3个ATM放在一个小镇上-你希望所有三个线程(ATM)能够在同一时间向/从同一个帐户存款和重新提取资金,如果需要的话 如果不同步,则会发生竞争情况。让我们看看: 银行存款是100美元。A想存20美元的人。B个人想存50美元。C个人想重画130美元。如果人员A在人员B存款之前存款(发生在人员C重画之前),则这是可能的。但问题是 在某人存款之前,账户上有100美元。存款方法可以如下所示:
// Naive deposit
public void deposit(double amount) {
double currentAmount = getCurrentAmount(); // Critical
setCurrentAmount(currentAmount + amount);
}
当某人存款时,ATM机需要取回当前金额,将此人想要存款的金额加起来,并将当前余额设置为该金额。然而,在临界点(标记为//Critial
)处,人员B也可能已存款。如果ATM a(人员a的ATM)和ATM B(人员B的ATM)在同一时间存款,那么可能出现的问题如下:
- ATM A检索当前金额$返回100
- ATM B检索当前金额$返回100
- ATM B将当前金额更新为$100+$50=$150
- ATM B将150美元作为账户总金额存储
- ATM A认为账户上只有100美元,于是将总余额更新为120美元
现在转到
synchronized
关键字!这个关键字在方法上放置了一个虚拟锁,这意味着只有为这个“锁”提供了“密钥”的线程(ATM)才能执行代码。所有其他线程都必须等待具有此神奇“键”的线程完成。在上面的银行示例中,这意味着ATM A将在ATM B取回当前金额并再存入50美元之前完成向账户中存入20美元 你能把你的问题说得更具体些吗?在start方法中调用run()
方法没有意义(至少对我来说),可能是新线程(this).start()
?!并发性是一个复杂的主题。在使用多线程之前,您应该明确地了解您正在做什么。此程序不是线程安全的。幸运的是,它不会启动任何线程。因此,如果一个线程试图执行一个同步方法,而另一个同步方法尚未完成执行,那么同步这两个方法将确保第一个方法完全执行并完成,然后允许调用第二个方法的线程完全执行。只要他们尝试调用同一对象的方法。非常感谢,并感谢所有其他人的帮助!