同步做什么
synchronized
关键字意味着几件事
- 包围的部分
synchronized
不能有多个线程在由同一对象同步的区域中运行,换句话说,您可以保证同步访问,即如果isTrue
在false
同步部分中,则在当前内容中,除非由当前在同步部分中的线程执行它将保持该值。 - 这也意味着不会为了优化目的对操作进行重新排序
- 当用作方法描述符时,即具有具有以下样式的方法
public synchronized void doWork(Object parameter)
{
/*do stuff*/
}
转换为以下内容:
public synchronized void doWork(Object parameter)
{
synchronized(this)
{
/*do stuff*/
}
}
同步不会神奇地启动线程
您需要自己启动线程,我无法告诉您有多少次我发现人们认为仅仅因为您创建了一个方法或一个同步块就神奇地启动了一个线程而没有他们做任何工作,这是一种控制访问的方法到代码的关键部分。
创建一个新线程
有几种方法可以做到这一点,但最好的方法(IMO)是使用一个实现 Runnable 的类并让你的线程使用它
Recorder recordIn= new Recorder();
Scanner scanIn= new Scanner();
Thread threadRecord = new Thread(new Runnable() {
private final Recorder target = recordIn;
@Override
public void run() {
//do stuff in here
}
});
Thread threadScan = new Thread(new Runnable() {
private final Recorder targetsRecorder = recordIn;
private final Scanner target = scanIn;
@Override
public void run() {
//do stuff here
}
});
threadRecords.start();
threadScan.start();
确保您的代码有效
现在您需要确保您的同步代码有效。根据您要做什么,您将需要关注不同的事情。一个常用的例子是让一个线程在一个线程上等待,你可以通过等待对象句柄来做到这一点。例如,我想在每次注意到运动时扫描记录器。另外,请记住我是在没有 IDE 的情况下即时执行此操作的,并且我假设只有这两个线程在操作对象上
Thread threadRecord = new Thread(new Runnable() {
private final Recorder target = recordIn;
private final Scanner scanr= scanIn;
@Override
public void run() {
//if movement is noticed compared to the last frame save
recordIn.startRecording();
while(true){
synchronized(target ){
while(target.hasMore()){
synchronized(scanr)
{
while(!target.currentImage().equals(scanr.getLatestImage())
{
target.recordMore();
scanr.wait();
}
}
}
}
}
}
}
});
Thread threadScan = new Thread(new Runnable() {
private final Recorder targetsRecorder = recordIn;
private final Scanner target = scanIn;
@Override
public void run() {
//do stuff here
synchronized(target){
target.wait();
while(true)
{
while(!targetsRecorder.doneRecording() && targetsRecorder.currentImage().equals(scanIn.getLastImage()))
target.wait();
if(targetsRecorder.doneRecording())
return;
scanIn.scanCurrentImage(targetsRecorder);
}
}
}
}
});
threadScan.start();
threadRecord.start();
使用事件监听器执行此操作
正如您所说,您正在使用事件侦听器执行此操作,概念是相同的,只是在事件侦听器中启动一个新线程
//inside of your listner
public void someRecordEventHappened(RecordEvent event){
new Thread(new Runnable
{
private final RecordEvent eventDate = event;
@Override
public void run()
{
//do stuff asynchronously
}
}).start();
}