synchronized(this/object/类.class)的区别

本文通过三个实例详细解析了Java中synchronized关键字的三种使用方式:this、object和类.class的区别及其实现效果。通过对比不同锁机制下的线程运行情况,帮助读者理解不同场景下锁的使用特点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

synchronized this object Class的区别

首先放上结论:

1.this:相当于只有一把钥匙的多把锁,他可以锁住多个代码块,但是每次开锁只能一个,如果钥匙在其他代码块手上,那么新来的被锁的多个代码块就拿不到钥匙,进不了方自己的代码块

2.object:每一个object相当于一把锁,那么不同的锁会有不同的钥匙,这样如果自己的锁不同,一样的锁没有被其他人占据,自己开始能进入代码块

3.类.clss:这是静态的锁,应为静态就带有this的含义,所以不能用this,而用类.class

下面是代码

Main方法–其中线程使用lambda表达式
public class Mian {
    public static void main(String[] args) {
        Material m = new Material();
        new Thread(()->{
            m.doSome();
        }){

        }.start();


        Thread t2 = new Thread(new Runnable() {

            @Override
            public void run() {
                m.deOther();

            }
        });
        t2.start();
    }

}
object
class Material{
    private int data1=1;
    private int data2=2;
    private Object lock1 =new Object();
    private Object lock2 =new Object();
    public void doSome() {
        synchronized (lock1) {
            try {
                System.out.println(++data1);
                Thread.sleep(2000);
            }catch(Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void deOther() {
        synchronized (lock2) {
            System.out.println(data1);
        }

    }
}

/*-----------------
结果:
1
2//中间没有时间间隔
------------------*/
this
class Material{
    private int data1=1;
    private int data2=2;
    private Object lock1 =new Object();
    private Object lock2 =new Object();
    public void doSome() {
        synchronized (this) {
            try {
                System.out.println(++data1);
                Thread.sleep(2000);
            }catch(Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void deOther() {
        synchronized (this) {
            System.out.println(data1);
        }

    }
}


/*-----------------
结果:
1
2//中间时间间隔2秒
------------------*/
class
class Material{
    private static int data1=1;
    private int data2=2;
    private Object lock1 =new Object();
    private Object lock2 =new Object();
    public static void doSome() {
        synchronized (Material.class) {
            try {
                System.out.println(data1);
                Thread.sleep(2000);
            }catch(Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void deOther() {
        synchronized (this) {
            System.out.println(data1);
        }

    }
}
/*---------------
输出;
1
2//中间没有时间间隔
---------------*/
package com.example.demoapplication; // 定义包名 // 导入Android系统权限相关 import android.Manifest; import android.content.pm.PackageManager; // 导入音频处理相关的 import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioRecord; import android.media.AudioTrack; import android.media.MediaRecorder; // 导入Android基础组件和工具 import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.speech.tts.TextToSpeech; import android.util.Base64; import android.util.Log; import android.widget.Button; import android.widget.Toast; // 导入Android支持库相关 import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; // 导入JSON处理库 import org.json.JSONException; import org.json.JSONObject; // 导入IO和网络相关 import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket; // 导入数据结构和并发工具 import java.util.LinkedList; import java.util.Locale; import java.util.Queue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; // 主活动,继承自AppCompatActivity并实现TextToSpeech的初始化监听器 public class MainActivity extends AppCompatActivity implements TextToSpeech.OnInitListener { private static final String TAG = "AudioRecorder"; // 日志标签 private Button startRecordButton, stopRecordButton; // 录音控制按钮 private Button playSoundButton, pauseSoundButton, stopSoundButton, resumeSoundButton, clearSoundsButton; // 播放控制按钮 private AudioRecord audioRecord; // 音频录制对象 // 音频配置常量 private static final int SAMPLE_RATE = 16000; // 采样率 private static final int BUFFER_SIZE; // 缓冲区大小 // 静态代码块计算缓冲区大小 static { int minBufferSize = AudioRecord.getMinBufferSize( // 获取最小缓冲区大小 SAMPLE_RATE, // 采样率 AudioFormat.CHANNEL_IN_MONO, // 单声道输入 AudioFormat.ENCODING_PCM_16BIT // PCM 16位编码 ); BUFFER_SIZE = Math.max(minBufferSize, 4096); // 取最小缓冲区和4096中的较大值 } // 线程和状态管理 private ScheduledExecutorService scheduler; // 调度执行服务 private AtomicBoolean isRecording = new AtomicBoolean(false); // 原子布尔值表示是否正在录音 private static final int PERMISSION_REQUEST_CODE = 1; // 权限请求码 private final ExecutorService executorService = Executors.newCachedThreadPool(); // 执行服务 // 网络通信相关变量 private ServerSocket serverSocket; // 服务器Socket private volatile boolean isServerRunning = true; // 服务器运行状态 private volatile Socket clientSocket; // 客户端Socket private volatile BufferedWriter socketWriter; // Socket写入器 // TTS和播放控制 private TextToSpeech ttsEngine; // 文语转换引擎 private boolean isTtsInitialized = false; // TTS初始化状态 private AudioTrack audioTrack; // 音频播放轨道 // 录音队列和播放状态 private final Queue<byte[]> recordingQueue = new LinkedList<>(); // 录音数据队列 private final Queue<byte[]> pausedQueue = new LinkedList<>(); // 暂停时的数据队列 private final Queue<byte[]> playbackQueue = new LinkedList<>(); // 播放队列 private boolean isPlaying = false; // 是否正在播放 private boolean isPaused = false; // 是否已暂停 // 主线程Handler用于更新UI private final Handler handler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(@NonNull Message msg) { switch (msg.what) { case 0x11: // 客户端连接 Toast.makeText(MainActivity.this, "客户端已连接", Toast.LENGTH_SHORT).show(); break; case 0x12: // 开始录音 Toast.makeText(MainActivity.this, "开始录音", Toast.LENGTH_SHORT).show(); sendControlPacket("startRecorder"); // 发送开始录音控制包 playTts("开始录音"); // 播报语音提示 break; case 0x14: // 停止录音 Toast.makeText(MainActivity.this, "停止录音", Toast.LENGTH_SHORT).show(); sendControlPacket("stopRecorder"); // 发送停止录音控制包 playTts("停止录音"); // 播报语音提示 break; case 0x16: // 错误 Toast.makeText(MainActivity.this, "错误: " + msg.obj, Toast.LENGTH_LONG).show(); break; case 0x17: // 播放完成 Toast.makeText(MainActivity.this, "播放完成", Toast.LENGTH_SHORT).show(); isPlaying = false; // 更新播放状态 updatePlayButtonsState(); // 更新按钮状态 processNextPlaybackItem(); // 处理下一个播放项 break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 设置布局文件 // 初始化TTS引擎 ttsEngine = new TextToSpeech(this, this); initViews(); // 初始化视图组件 setupClickListeners(); // 设置点击事件监听器 checkPermissions(); // 检查权限 startServer(30000); // 启动服务器 } // 初始化视图组件 private void initViews() { startRecordButton = findViewById(R.id.startRecordButton); // 绑定开始录音按钮 stopRecordButton = findViewById(R.id.stopRecordButton); // 绑定停止录音按钮 playSoundButton = findViewById(R.id.playSoundButton); // 绑定播放按钮 pauseSoundButton = findViewById(R.id.pauseSoundButton); // 绑定暂停按钮 stopSoundButton = findViewById(R.id.stopSoundButton); // 绑定停止播放按钮 resumeSoundButton = findViewById(R.id.resumeSoundButton); // 绑定继续播放按钮 clearSoundsButton = findViewById(R.id.clearSoundsButton); // 绑定清除录音按钮 // 初始按钮状态设置 stopRecordButton.setEnabled(false); pauseSoundButton.setEnabled(false); stopSoundButton.setEnabled(false); resumeSoundButton.setEnabled(false); } // 设置按钮点击事件监听器 private void setupClickListeners() { startRecordButton.setOnClickListener(v -> startRecording()); // 开始录音点击事件 stopRecordButton.setOnClickListener(v -> stopRecording()); // 停止录音点击事件 playSoundButton.setOnClickListener(v -> addToPlaybackQueue()); // 添加到播放队列点击事件 pauseSoundButton.setOnClickListener(v -> pausePlayback()); // 暂停播放点击事件 stopSoundButton.setOnClickListener(v -> stopPlayback()); // 停止播放点击事件 resumeSoundButton.setOnClickListener(v -> resumePlayback()); // 继续播放点击事件 clearSoundsButton.setOnClickListener(v -> clearAllRecordings()); // 清除录音点击事件 } // ==================== 录音功能实现 ==================== // 开始录音方法 private void startRecording() { // 检查录音权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { sendErrorMessage("没有录音权限"); return; } // 如果已经在录音,释放资源 if (isRecording.get()) { releaseAudioResources(); // 确保所有队列都清空后再重新初始化 synchronized (recordingQueue) { recordingQueue.clear(); } synchronized (playbackQueue) { playbackQueue.clear(); } pausedQueue.clear(); } try { // 初始化录音器 audioRecord = new AudioRecord( MediaRecorder.AudioSource.MIC, // 麦克风作为音频源 SAMPLE_RATE, // 采样率 AudioFormat.CHANNEL_IN_MONO, // 单声道输入 AudioFormat.ENCODING_PCM_16BIT, // PCM 16位编码 BUFFER_SIZE // 缓冲区大小 ); // 检查录音器是否初始化成功 if (audioRecord.getState() != AudioRecord.STATE_INITIALIZED) { throw new IllegalStateException("AudioRecord 初始化失败"); } // 开始录音 audioRecord.startRecording(); isRecording.set(true); // 更新录音状态 // 清空之前的录音数据(确保同步synchronized (recordingQueue) { recordingQueue.clear(); } pausedQueue.clear(); // 更新UI状态 startRecordButton.setEnabled(false); stopRecordButton.setEnabled(true); updatePlayButtonsState(); // 启动录音数据采集线程 if (scheduler != null) { scheduler.shutdownNow(); // 关闭之前的调度器 } scheduler = Executors.newSingleThreadScheduledExecutor(); // 创建新的单线程调度器 scheduler.scheduleAtFixedRate(this::captureAudioData, 0, 100, TimeUnit.MILLISECONDS); // 每100毫秒采集一次音频数据 // 发送开始录音通知 handler.sendEmptyMessage(0x12); // 发送消息给Handler sendControlPacket("startRecorder"); // 发送开始录音控制包 playTts("开始录音"); // 播报语音提示 } catch (Exception e) { Log.e(TAG, "录音启动失败", e); // 记录错误日志 sendErrorMessage("录音启动失败: " + e.getMessage()); // 发送错误信息 releaseAudioResources(); // 释放音频资源 } } // 停止录音方法 private void stopRecording() { if (!isRecording.get()) return; // 如果不在录音直接返回 isRecording.set(false); // 更新录音状态 releaseAudioResources(); // 释放音频资源 // 更新UI状态 stopRecordButton.setEnabled(false); startRecordButton.setEnabled(true); updatePlayButtonsState(); // 发送停止录音通知 handler.sendEmptyMessage(0x14); // 发送消息给Handler sendControlPacket("stopRecorder"); // 发送停止录音控制包 playTts("停止录音"); // 播报语音提示 } // 采集音频数据并保存到队列 private void captureAudioData() { if (!isRecording.get() || audioRecord == null) return; // 如果不在录音或录音器为空直接返回 byte[] buffer = new byte[BUFFER_SIZE]; // 创建缓冲区 try { int bytesRead = audioRecord.read(buffer, 0, BUFFER_SIZE); // 读取音频数据 if (bytesRead > 0) { // 将录制的音频数据保存到队列 synchronized (recordingQueue) { // 同步操作 recordingQueue.offer(buffer.clone()); // 添加拷贝到队列中 } } } catch (Exception e) { Log.e(TAG, "音频采集失败", e); // 记录错误日志 } } // ==================== 录音功能结束 ==================== // ==================== 播放功能实现 ==================== // 添加到播放队列 private void addToPlaybackQueue() { if (recordingQueue.isEmpty()) { // 如果队列为空 Toast.makeText(this, "没有可播放的录音", Toast.LENGTH_SHORT).show(); // 显示提示 return; } // 创建录音数据副本 Queue<byte[]> recordingCopy = new LinkedList<>(); synchronized (recordingQueue) { for (byte[] data : recordingQueue) { recordingCopy.offer(data.clone()); } } // 添加到播放队列 synchronized (playbackQueue) { playbackQueue.addAll(recordingCopy); } // 如果当前没有播放,立即开始播放 if (!isPlaying && !isPaused) { executorService.execute(this::playRecordingQueue); } else { Toast.makeText(this, "已添加到播放队列", Toast.LENGTH_SHORT).show(); } } // 播放录音队列 private void playRecordingQueue() { isPlaying = true; // 更新播放状态 isPaused = false; // 更新暂停状态 updatePlayButtonsState(); // 更新按钮状态 // 配置音频播放器 int bufferSize = AudioTrack.getMinBufferSize( // 获取最小缓冲区大小 SAMPLE_RATE, // 采样率 AudioFormat.CHANNEL_OUT_MONO, // 单声道输出 AudioFormat.ENCODING_PCM_16BIT // PCM 16位编码 ); // 创建音频播放器 audioTrack = new AudioTrack( AudioManager.STREAM_MUSIC, // 音乐流型 SAMPLE_RATE, // 采样率 AudioFormat.CHANNEL_OUT_MONO, // 单声道输出 AudioFormat.ENCODING_PCM_16BIT, // PCM 16位编码 bufferSize, // 缓冲区大小 AudioTrack.MODE_STREAM // 流模式 ); audioTrack.play(); // 开始播放 // 播放队列中的所有录音数据 while (isPlaying && !playbackQueue.isEmpty()) { // 当正在播放且队列不为空时循环 if (isPaused) { // 如果处于暂停状态 // 暂停状态,等待恢复 try { Thread.sleep(100); // 等待100毫秒 } catch (InterruptedException e) { Thread.currentThread().interrupt(); // 中断线程 } continue; // 继续循环 } byte[] audioData; // 音频数据 synchronized (playbackQueue) { // 同步操作 audioData = playbackQueue.poll(); // 从队列取出数据 } if (audioData != null) { // 如果有数据 if (audioTrack != null) { // 确保audioTrack未被释放 audioTrack.write(audioData, 0, audioData.length); // 写入音频数据 } } } // 播放完成 stopPlayback(); // 停止播放 handler.sendEmptyMessage(0x17); // 发送播放完成消息 } // 处理下一个播放项 private void processNextPlaybackItem() { if (!playbackQueue.isEmpty()) { executorService.execute(this::playRecordingQueue); } } // 暂停播放 private void pausePlayback() { if (!isPlaying || isPaused) return; // 如果不在播放或已经暂停直接返回 isPaused = true; // 更新暂停状态 // 保存当前播放位置 synchronized (playbackQueue) { // 同步操作 pausedQueue.clear(); // 清空暂停队列 pausedQueue.addAll(playbackQueue); // 将播放队列添加到暂停队列 playbackQueue.clear(); // 清空播放队列 } updatePlayButtonsState(); // 更新按钮状态 Toast.makeText(this, "播放已暂停", Toast.LENGTH_SHORT).show(); // 显示提示 } // 继续播放 private void resumePlayback() { if (!isPlaying || !isPaused) return; // 如果不在播放或未暂停直接返回 isPaused = false; // 更新暂停状态 // 恢复播放位置 synchronized (playbackQueue) { // 同步操作 playbackQueue.clear(); // 清空播放队列 playbackQueue.addAll(pausedQueue); // 将暂停队列添加到播放队列 pausedQueue.clear(); // 清空暂停队列 } updatePlayButtonsState(); // 更新按钮状态 Toast.makeText(this, "继续播放", Toast.LENGTH_SHORT).show(); // 显示提示 // 启动播放线程 executorService.execute(this::playRecordingQueue); // 在线程池中执行播放任务 } // 停止播放 private void stopPlayback() { isPlaying = false; // 更新播放状态 isPaused = false; // 更新暂停状态 if (audioTrack != null) { // 如果音频轨道存在 try { if (audioTrack.getPlayState() == AudioTrack.PLAYSTATE_PLAYING) { // 如果正在播放 audioTrack.stop(); // 停止播放 } audioTrack.release(); // 释放资源 } catch (Exception e) { Log.e(TAG, "释放AudioTrack失败", e); // 记录错误日志 } audioTrack = null; // 置空引用 } synchronized (playbackQueue) { playbackQueue.clear(); // 清空播放队列 pausedQueue.clear(); // 清空暂停队列 } updatePlayButtonsState(); // 更新按钮状态 Toast.makeText(this, "播放已停止", Toast.LENGTH_SHORT).show(); // 显示提示 } // 清除所有录音 private void clearAllRecordings() { stopPlayback(); // 停止播放 synchronized (recordingQueue) { // 同步操作 recordingQueue.clear(); // 清空录音队列 pausedQueue.clear(); // 清空暂停队列 } synchronized (playbackQueue) { playbackQueue.clear(); // 清空播放队列 } updatePlayButtonsState(); // 更新按钮状态 Toast.makeText(this, "所有录音已清除", Toast.LENGTH_SHORT).show(); // 显示提示 } // ==================== 播放功能结束 ==================== // ==================== 辅助方法 ==================== // 更新播放按钮状态 private void updatePlayButtonsState() { runOnUiThread(() -> { // 在主线程执行 boolean hasRecordings = !recordingQueue.isEmpty() || !pausedQueue.isEmpty(); // 是否有录音 boolean isPlayingState = isPlaying && !isPaused; // 是否正在播放 playSoundButton.setEnabled(hasRecordings && !isPlayingState); // 设置播放按钮状态 pauseSoundButton.setEnabled(isPlayingState); // 设置暂停按钮状态 stopSoundButton.setEnabled(isPlaying); // 设置停止按钮状态 resumeSoundButton.setEnabled(isPlaying && isPaused); // 设置继续按钮状态 clearSoundsButton.setEnabled(hasRecordings); // 设置清除按钮状态 }); } // 播放TTS语音 private void playTts(String text) { if (isTtsInitialized) { // 如果TTS已初始化 ttsEngine.speak(text, TextToSpeech.QUEUE_FLUSH, null); // 播报文本 } } // 释放音频资源 private void releaseAudioResources() { if (audioRecord != null) { // 如果录音器存在 try { if (audioRecord.getRecordingState() == AudioRecord.RECORDSTATE_RECORDING) { // 如果正在录音 audioRecord.stop(); // 停止录音 } } catch (IllegalStateException e) { Log.e(TAG, "停止录音失败", e); // 记录错误日志 } audioRecord.release(); // 释放资源 audioRecord = null; // 置空引用 } if (scheduler != null) { // 如果调度器存在 scheduler.shutdownNow(); // 关闭调度器 scheduler = null; // 置空引用 } } // 发送控制包 private void sendControlPacket(String type) { if (clientSocket == null || clientSocket.isClosed() || socketWriter == null) { // 如果连接无效 return; // 直接返回 } try { JSONObject packet = new JSONObject(); // 创建JSON对象 packet.put("type", type); // 添加型字段 synchronized (this) { // 同步操作 if (socketWriter != null) { // 如果写入器存在 socketWriter.write(packet.toString()); // 写入JSON字符串 socketWriter.write("\n\n"); // 写入两个换行符 socketWriter.flush(); // 刷新缓冲区 } } } catch (Exception e) { Log.e(TAG, "发送控制指令失败", e); // 记录错误日志 } } // 发送错误消息 private void sendErrorMessage(String message) { handler.obtainMessage(0x16, message).sendToTarget(); // 发送错误消息 } // 检查权限 private void checkPermissions() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) // 检查录音权限 != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, // 请求权限 new String[]{Manifest.permission.RECORD_AUDIO}, // 权限数组 PERMISSION_REQUEST_CODE); // 请求码 } } // 启动服务器 private void startServer(int port) { executorService.execute(() -> { // 在线程池中执行 try { serverSocket = new ServerSocket(port); // 创建服务器Socket Log.i(TAG, "服务器启动: " + port); // 记录日志 while (isServerRunning) { // 当服务器运行时循环 try { Socket socket = serverSocket.accept(); // 接受连接 clientSocket = socket; // 保存客户端Socket synchronized (this) { // 同步操作 socketWriter = new BufferedWriter( // 创建缓冲写入器 new OutputStreamWriter(socket.getOutputStream(), "UTF-8")); // 使用UTF-8编码 } handler.sendEmptyMessage(0x11); // 发送客户端连接消息 executorService.execute(() -> startCommunication(socket)); // 启动通信线程 } catch (IOException e) { if (isServerRunning) Log.e(TAG, "接受连接失败", e); // 记录错误日志 } } } catch (IOException e) { Log.e(TAG, "服务器启动失败", e); // 记录错误日志 runOnUiThread(() -> Toast.makeText(this, // 显示提示 "服务器启动失败: " + e.getMessage(), Toast.LENGTH_LONG).show()); } finally { closeServerSocket(); // 关闭服务器Socket } }); } // 关闭服务器Socket(空实现) private void closeServerSocket() { } // 开始通信(空实现) private void startCommunication(Socket socket) { } // 其他网络通信相关方法保持不变... // 为了简洁省略了部分网络通信代码,实际使用时需要完整实现 // TTS初始化回调 @Override public void onInit(int status) { if (status == TextToSpeech.SUCCESS) { // 如果初始化成功 int result = ttsEngine.setLanguage(Locale.CHINESE); // 设置中文语言 if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) { // 如果不支持 Log.e(TAG, "TTS语言不支持中文"); // 记录日志 } else { isTtsInitialized = true; // 更新初始化状态 } } } // 销毁活动时调用 @Override protected void onDestroy() { super.onDestroy(); // 调用父方法 isServerRunning = false; // 停止服务器 if (ttsEngine != null) { // 如果TTS引擎存在 ttsEngine.stop(); // 停止TTS ttsEngine.shutdown(); // 关闭TTS } closeServerSocket(); // 关闭服务器Socket closeSocket(clientSocket); // 关闭客户端Socket executorService.shutdownNow(); // 关闭线程池 releaseAudioResources(); // 释放音频资源 stopPlayback(); // 停止播放 } // 关闭Socket(空实现) private void closeSocket(Socket clientSocket) { } } 解决播放完录音app就会闪退
最新发布
07-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值