addShutdownHook()方法要点

这句话是关键的:由于用户注销或系统关闭而终止虚拟机时,底层的操作系统可能只允许在固定的时间内关闭并退出。因此在关闭挂钩中尝试进行任何用户交互或执行长时间的计算都是不明智的。

我写的方法过多,导致没法执行

import java.io.DataInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.net.Socket; public class Main { public static void main(String[] args) { String adbPath = "adb"; // 你的adb路径 ADBExecutor adbExecutor = new ADBExecutor(adbPath); AdbDeviceListener listener = new AdbDeviceListener(adbExecutor, 2000, new AdbDeviceListener.OnDevice() { @Override public void onDeviceCR(String deviceName) { System.out.println("插入USB设备: " + deviceName); adbExecutor.execAdbSingleDevicePortForward(deviceName, ADBExecutor.HOST_PORT, ADBExecutor.ANDROID_PORT); if (AdbDeviceListener.connectToDevice(ADBExecutor.HOST_PORT)) { System.out.println("连接成功,开始监听来自 Android 的音频数据..."); receiveLiveAudioData(AdbDeviceListener.deviceSocket); } else { System.out.println("连接失败"); } } @Override public void onDeviceBC(String deviceName) { System.out.println("拔出USB设备: " + deviceName); } }); listener.start(); Runtime.getRuntime().addShutdownHook(new Thread(() -> { System.out.println("程序关闭,停止监听"); listener.stop(); })); } private static void receiveLiveAudioData(Socket socket) { new Thread(() -> { try (DataInputStream dis = new DataInputStream(socket.getInputStream())) { // 创建保存音频数据的文件 File saveDir = new File("D://文件/"); if (!saveDir.exists()) saveDir.mkdirs(); String liveFileName = "live_stream.mp3"; File outputFile = new File(saveDir, liveFileName); try (FileOutputStream fos = new FileOutputStream(outputFile, true)) { byte[] buffer = new byte[4096]; while (true) { // 持续接收数据,每160ms 上传一次音频数据 long startTime = System.currentTimeMillis(); int bytesRead = dis.read(buffer); System.err.println(buffer.toString()); System.out.println("收收收"); if (bytesRead == -1) { break; // 连接断开 } fos.write(buffer, 0, bytesRead); fos.flush(); long elapsedTime = System.currentTimeMillis() - startTime; long sleepTime = 160 - elapsedTime; // 每160ms上传一次 if (sleepTime > 0) { Thread.sleep(sleepTime); // 控制上传频率 } } System.out.println("音频数据接收完成: " + liveFileName); } catch (IOException | InterruptedException e) { System.out.println("接收音频数据异常: " + e.getMessage()); } } catch (IOException e) { e.printStackTrace(); System.out.println("接收音频数据异常中止: " + e.getMessage()); } }).start(); } } 生成python脚本
06-21
import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import lombok.extern.slf4j.Slf4j; /** * Description of this file * * @author Deng Peihao * @version 1.0 * @since 2025/8/22 */ @Slf4j public class MyNettyServer { public static void main(String[] args) throws Exception { //创建两个线程组 boosGroup、workerGroup EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { //创建服务端的启动对象,设置参数 ServerBootstrap bootstrap = new ServerBootstrap(); //设置两个线程组boosGroup和workerGroup bootstrap.group(bossGroup, workerGroup) //设置服务端通道实现类型 .channel(NioServerSocketChannel.class) //设置线程队列得到连接个数 .option(ChannelOption.SO_BACKLOG, 128) //设置保持活动连接状态 .childOption(ChannelOption.SO_KEEPALIVE, true) //使用匿名内部类的形式初始化通道对象 .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { //给pipeline管道设置处理器 socketChannel.pipeline() .addLast(new MyMessageDecoder()) .addLast(new MyMessageEncoder()) .addLast(new MyNettyServerHandler()); } });//给workerGroup的EventLoop对应的管道设置处理器 log.info("server start"); //绑定端口号,启动服务端 ChannelFuture channelFuture = bootstrap.bind(6666).sync(); //对关闭通道进行监听 channelFuture.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } }改为可以开启关闭的服务
最新发布
08-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值