如何暂停与恢复IO任务?协程及非协程实现方案咨询
非协程方式实现可暂停/恢复的文件复制操作
要实现可暂停、恢复的文件复制IO任务,核心思路是分块执行文件传输,配合线程安全的状态标记和等待/唤醒机制,让IO线程能响应Main线程的控制指令。以下是具体实现方案:
1. 定义复制控制器(线程安全的状态管理)
先创建一个控制器类,统一管理复制任务的暂停、恢复状态及复制线程:
import java.nio.channels.FileChannel import java.nio.file.Paths import java.nio.file.StandardOpenOption import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.locks.Condition import java.util.concurrent.locks.ReentrantLock class FileCopyController { private val lock = ReentrantLock() private val pauseCondition: Condition = lock.newCondition() private val isPaused = AtomicBoolean(false) private var copyThread: Thread? = null // 暂停复制 fun pause() { isPaused.set(true) } // 恢复复制 fun resume() { lock.lock() try { isPaused.set(false) pauseCondition.signal() // 唤醒等待的复制线程 } finally { lock.unlock() } } // 启动复制任务 fun startCopy(sourcePath: String, targetPath: String) { copyThread = Thread { val bufferSize = 8 * 1024 * 1024 // 8MB分块,可根据需求调整 try { FileChannel.open(Paths.get(sourcePath), StandardOpenOption.READ).use { sourceChannel -> FileChannel.open(Paths.get(targetPath), StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW).use { targetChannel -> var transferred = 0L val fileSize = sourceChannel.size() while (transferred < fileSize) { // 检查是否需要暂停,若暂停则进入等待 while (isPaused.get()) { lock.lock() try { pauseCondition.await() } finally { lock.unlock() } } // 分块传输数据 val bytesTransferred = sourceChannel.transferTo(transferred, bufferSize.toLong(), targetChannel) if (bytesTransferred == 0L) break // 传输完成 transferred += bytesTransferred } } } } catch (e: Exception) { e.printStackTrace() if (e is InterruptedException) { Thread.currentThread().interrupt() // 保留中断标记 } } } copyThread?.start() } // 强制终止复制任务(可选) fun stopCopy() { copyThread?.interrupt() copyThread = null } }
2. 在Main线程中绑定按键事件
在UI层(Dispatchers.Main线程)的按键点击逻辑中,直接调用控制器的对应方法即可实现控制:
// 初始化控制器 val copyController = FileCopyController() // 启动复制按钮点击事件 startButton.setOnClickListener { val source = """D:\Games\Eg.7z""" val target = """D:\New folder\Eg.7z""" copyController.startCopy(source, target) } // 暂停按钮点击事件 pauseButton.setOnClickListener { copyController.pause() } // 恢复按钮点击事件 resumeButton.setOnClickListener { copyController.resume() }
关键说明
- 分块传输:通过
FileChannel.transferTo()分块处理文件,避免一次性阻塞整个IO操作,让线程有机会检查暂停状态。 - 线程安全状态:用
AtomicBoolean标记暂停状态,配合ReentrantLock和Condition实现线程的等待/唤醒,确保Main线程与IO线程的状态交互安全。 - 中断处理:若需强制终止任务,可调用
stopCopy()中断复制线程,需正确处理InterruptedException以保证线程状态正确。
内容的提问来源于stack exchange,提问作者Cyber Avater
相关产品推荐
相关产品推荐

