javafx.concurrent中包含:
1个接口Worker<V>,
4个类:
1个枚举javafx.concurrent.Worker.State,代表Worker的不同状态READY,SCHEDULED,RUNNING,SUCCEEDED,CANCELLED,FAILED
Task,Service,ScheduledService等3个类均为抽象类,均实现了Worker<V>接口,代表不同的任务类型
import javafx.application.Platform
import javafx.beans.binding.Bindings
import tornadofx.*
import javafx.beans.binding.When
import javafx.collections.ObservableList
import javafx.concurrent.Worker
import kotlin.math.ceil
import kotlin.math.sqrt
import javafx.collections.FXCollections
import javafx.concurrent.ScheduledService
import javafx.concurrent.Service
import javafx.concurrent.Task
import javafx.concurrent.Worker.State.READY
import javafx.concurrent.Worker.State.RUNNING
import javafx.concurrent.Worker.State.SCHEDULED
import javafx.scene.layout.BorderStrokeStyle.SOLID
import javafx.scene.paint.Color
import javafx.util.Duration
class FxConcurrentApp : App(FxConcurrentView::class,Mystyle::class)
class FxConcurrentView : View("A Prime Number Finder Task") {
// Create the service
// ScheduledService在任务执行成功或失败后可自动重启
private var service: ScheduledService<ObservableList<Long>> = object : ScheduledService<ObservableList<Long>>() {
override fun createTask(): Task<ObservableList<Long>> {
return PrimeFinderTask()
}
}
var onceStarted = false
override val root = borderpane {
paddingAll = 10.0
top = hbox(5) {
service.delay = Duration.seconds(2.0)
service.period = Duration.seconds(3.0)
service.maximumFailureCount = 5
button("Start") {
action {
if (onceStarted) {
// restart()方法会依次调用cancel(),reset(),start()等3个方法
service.restart()
} else {
service.start()
onceStarted = true
text = "Restart"
}
}
}
button("Cancel") {
disableProperty().bind(service.stateProperty().isNotEqualTo(RUNNING))
action {
service.cancel()
}
}
button("Exit") {
action {
Platform.exit()
}
}
button("Reset") {
disableProperty().bind(Bindings.or(service.stateProperty().isEqualTo(RUNNING),
service.stateProperty().isEqualTo(SCHEDULED)))
action {
service.reset()
}
}
}
center {
add(WorkerStateGUI(service))
}
}
}
class FxConcurrentView2 : View("A Prime Number Finder Task") {
// Create the service
// Service<V>类是接口Worker<V>的抽象实现,它包装了抽象类Task<V>,
// 让Task<V>可以开始start,取消cancell,重置reset和重新开始restart,
// Service<V>抽象类包含createTask()抽象方法,访方法返回Task<V>实例
private var service: Service<ObservableList<Long>> = object : Service<ObservableList<Long>>() {
override fun createTask(): Task<ObservableList<Long>> {
return PrimeFinderTask()
}
}
var onceStarted = false
override val root = borderpane {
paddingAll = 10.0
top = hbox(5) {
button("Start") {
action {
if (onceStarted) {
service.restart()
} else {
service.start()
onceStarted = true
text = "Restart"
}
}
}
button("Cancel") {
disableProperty().bind(service.stateProperty().isNotEqualTo(RUNNING))
action {
service.cancel()
}
}
button("Reset") {
disableProperty().bind(Bindings.or(service.stateProperty().isEqualTo(RUNNING),
service.stateProperty().isEqualTo(SCHEDULED)))
action {
service.reset()
}
}
button("Exit") {
action {
Platform.exit()
}
}
}
center {
add(WorkerStateGUI(service))
}
}
}
class FxConcurrentView1 : View("A Prime Number Finder Task") {
var task = PrimeFinderTask()
override val root = borderpane {
paddingAll = 10.0
top = hbox(5) {
button("Start") {
disableProperty().bind(task.stateProperty().isNotEqualTo(READY))
action {
startTask()
}
}
button("Cancel") {
disableProperty().bind(task.stateProperty().isNotEqualTo(RUNNING))
action {
task.cancel()
}
}
button("Exit") {
action {
Platform.exit()
}
}
}
center {
add(WorkerStateGUI(task))
}
}
private fun startTask() {
// Schedule the task on a background thread
val backgroundThread = Thread(task)
backgroundThread.isDaemon = true
backgroundThread.start()
}
}
class WorkerStateGUI() : Fragment() {
constructor(worker: Worker<ObservableList<Long>>) : this() {
bindToWorker(worker)
}
private val title0 = stringProperty("")
private val message = stringProperty("")
private val running = stringProperty("")
private val state = stringProperty("")
private val totalWork = stringProperty("")
private val workDone = stringProperty("")
private val value0 = stringProperty("")
private val progress = stringProperty("")
private val exception = stringProperty("")
private val progressbar0 = doubleProperty(0.0)
override val root = form {
fieldset {
field("Title:") {
label(title0)
}
field("Message:") {
label(message)
}
field("Running:") {
label(running)
}
field("State:") {
label(state)
}
field("Total Work:") {
label(totalWork)
}
field("Work Done:") {
label(workDone)
}
field("Progress:") {
progressbar(progressbar0)
label(progress)
}
field("Value:") {
textarea(value0) {
prefRowCount = 3
prefColumnCount = 20
}
}
field("Exception:") {
textarea(exception) {
prefRowCount = 3
prefColumnCount = 20
}
}
}
}
private fun bindToWorker(worker: Worker<ObservableList<Long>>) {
// Bind Labels to the properties of the worker
title0.bind(worker.titleProperty())
message.bind(worker.messageProperty())
running.bind(worker.runningProperty().asString())
state.bind(worker.stateProperty().asString())
totalWork.bind(
When(worker.totalWorkProperty().isEqualTo(-1)).then("Unknown")
.otherwise(worker.totalWorkProperty().asString()))
workDone.bind(
When(worker.workDoneProperty().isEqualTo(-1)).then("Unknown")
.otherwise(worker.workDoneProperty().asString()))
progress.bind(
When(worker.progressProperty().isEqualTo(-1)).then("Unknown")
.otherwise(worker.progressProperty().multiply(100.0).asString("%.2f%%")))
progressbar0.bind(worker.progressProperty())
value0.bind(worker.valueProperty().asString())
worker.exceptionProperty().addListener { _, _, newValue ->
if (newValue != null) {
exception.value = newValue.message
} else {
exception.value = ""
}
}
}
}
object PrimeUtil {
fun isPrime(num: Long): Boolean {
if (num <= 1 || num % 2 == 0L) {
return false
}
val upperDivisor = ceil(sqrt(num.toDouble())).toInt()
var divisor = 3
while (divisor <= upperDivisor) {
if (num % divisor == 0L) {
return false
}
divisor += 2
}
return true
}
}
class PrimeFinderTask : Task<ObservableList<Long>> {
// Define the Limits
private var lowerLimit: Long = 1
private var upperLimit: Long = 10
private var sleepTimeInMillis: Long = 100
constructor()
constructor(lowerLimit: Long, upperLimit: Long) {
this.lowerLimit = lowerLimit
this.upperLimit = upperLimit
}
constructor(lowerLimit: Long, upperLimit: Long, sleepTimeInMillis: Long) : this(lowerLimit, upperLimit) {
this.sleepTimeInMillis = sleepTimeInMillis
}
// The task implementation
override fun call(): ObservableList<Long> {
// An observable list to represent the results
val results = FXCollections.observableArrayList<Long>()
// Update the title
this.updateTitle("Prime Number Finder Task")
val count = this.upperLimit - this.lowerLimit + 1
var counter: Long = 0
// Find the prime numbers
for (i in lowerLimit..upperLimit) {
// Check if the task is cancelled
if (this.isCancelled) {
break
}
// Increment the counter
counter++
// Update message
this.updateMessage("Checking $i for a prime number")
// Sleep for some time
try {
Thread.sleep(this.sleepTimeInMillis)
} catch (e: InterruptedException) {
// Check if the task is cancelled
if (this.isCancelled) {
break
}
}
// Check if the number is a prime number
if (PrimeUtil.isPrime(i)) {
// Add to the list
results.add(i)
// Publish the read-only list to give the GUI
// access to the partial results
updateValue(FXCollections.unmodifiableObservableList(results))
}
// Update the progress
updateProgress(counter, count)
}
return results
}
override fun cancelled() {
super.cancelled()
updateMessage("The task was cancelled.")
}
override fun failed() {
super.failed()
updateMessage("The task failed.")
}
override fun succeeded() {
super.succeeded()
updateMessage("The task finished successfully.")
}
}
class Mystyle:Stylesheet(){
init {
root{
padding= box(10.px)
borderWidth+=box(2.px)
borderInsets+=box(5.px)
borderRadius+=box(5.px)
borderColor+= box(Color.BLUE)
borderStyle+=SOLID
}
}
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。