For example
import scala.actors.Actor
import scala.actors.Actor._
object Main {
class Pong extends Actor {
def act() {
var pongCount = 0
while (true) {
receive {
case "Ping" =>
if (pongCount % 1000 == 0)
Console.println("Pong: ping "+pongCount)
sender ! "Pong"
pongCount = pongCount + 1
case "Stop" =>
Console.println("Pong: stop")
exit()
}
}
}
}
class Ping(count: Int, pong: Actor) extends Actor {
def act() {
var pingsLeft = count - 1
pong ! "Ping"
while (true) {
receive {
case "Pong" =>
if (pingsLeft % 1000 == 0)
Console.println("Ping: pong")
if (pingsLeft > 0) {
pong ! "Ping"
pingsLeft -= 1
} else {
Console.println("Ping: stop")
pong ! "Stop"
exit()
}
}
}
}
}
def main(args: Array[String]): Unit = {
val pong = new Pong
val ping = new Ping(100000, pong)
ping.start
pong.start
println("???")
}
}
I try to print "???" after the two actors call exit(), but now it is printed before "Ping: Stop" and "Pong stop"
I have try have a flag in the actor, flag is false while actor is running, and flag is true when actor stops, and in the main func, there is a while loop, such as while (actor.flag == false) {}, but it doesn't works, it is a endless loop:-/
So, please give me some advice.
If you need synchronous calls in akka, use ask pattern. Like
Await.result(ping ? "ping")
Also, you'd better use actor system to create actors.
import akka.actor.{ActorRef, Props, Actor, ActorSystem}
import akka.pattern.ask
import akka.util.Timeout
import scala.concurrent.Await
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
object Test extends App {
implicit val timeout = Timeout(3 second)
val system = ActorSystem("ActorSystem")
class Pong extends Actor {
def receive: Receive = {
case "Ping" =>
println("ping")
context.stop(self)
}
}
lazy val pong = system.actorOf(Props(new Pong), "Pong")
val x = pong.ask("Ping")
val res = Await.result(x, timeout.duration)
println("????")
system.shutdown()
}
Related
I have one thread receiving packets from a local server:
// Shared object:
#Volatile lateinit var recentPacket: Packet
val recvMutex = Object()
// Thread code:
thread(isDaemon = true) {
while (true) {
val packet = readPacket()
synchronized(recvMutex) {
recentPacket = packet
recvMutex.notifyAll()
}
}
}
And I have multiple other threads waiting for packets, each of which should get the same packet that was just received:
suspend fun receive() {
return synchronized(recvMutex) {
recvMutex.wait() // non-blocking alternative to this?
recentPacket
}
}
It works, but Object.wait() blocks the thread. Is there a way to avoid this?
It works, but Object.wait() blocks the thread. Is there a way to avoid this?
Yes, but it means removing the complete wait-notify idiom you use now and replacing it with Kotlin's native BroadcastChannel.
Here is a basic example with two receivers and five packets being broadcast:
import kotlinx.coroutines.experimental.asCoroutineDispatcher
import kotlinx.coroutines.experimental.channels.BroadcastChannel
import kotlinx.coroutines.experimental.channels.SubscriptionReceiveChannel
import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.runBlocking
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
private val threadPool = Executors.newCachedThreadPool() as ExecutorService
val MyPool = threadPool.asCoroutineDispatcher()
fun main(args: Array<String>) {
val packetChannel = BroadcastChannel<Packet>(1)
(1..2).forEach {
launch(MyPool) {
receivePackets(it, packetChannel.openSubscription())
}
}
runBlocking {
(1..5).forEach {
packetChannel.send(Packet(it))
delay(100)
}
}
threadPool.shutdown()
}
suspend fun receivePackets(index: Int, packetChannel: SubscriptionReceiveChannel<Packet>) {
while (true) {
println("Receiver $index got packet ${packetChannel.receive().value}")
}
}
data class Packet(
val value: Int
)
Expect to see output such as this:
Receiver 1 got packet 1
Receiver 2 got packet 1
Receiver 2 got packet 2
Receiver 1 got packet 2
Receiver 1 got packet 3
Receiver 2 got packet 3
Receiver 1 got packet 4
Receiver 2 got packet 4
Receiver 1 got packet 5
Receiver 2 got packet 5
Coroutines seem to be in an experimental state; I suggest waiting until those mature before using them. See https://kotlinlang.org/docs/reference/coroutines.html#experimental-status-of-coroutines
I the mean time, you might try a ThreadPool:
import java.net.DatagramPacket
import java.net.DatagramSocket
import java.util.concurrent.Executors
import kotlin.concurrent.thread
fun start() {
val pool = Executors.newFixedThreadPool(10)
thread(isDaemon = true) {
val socket = DatagramSocket(12345)
while (!socket.isClosed) {
val packet = DatagramPacket(ByteArray(1000), 0)
socket.receive(packet)
pool.submit({
receive(packet)
})
}
}
pool.shutdown()
}
fun receive(packet: DatagramPacket) {
println(String(packet.data, 0, packet.length))
}
Asynchronous IO might be useful; You can look into Java Selectors
I'm trying to embed ZMQ subscriber in a Runnable.
I'm able to start the Runnable for the first time and everything seems okay.
The problem is when I interrupt the Thread and try to start a new Thread, the subscriber does not get any messages. For example:
I have a publisher runnable
class ZMQPublisherRunnable() extends Runnable {
override def run() {
val ZMQcontext = ZMQ.context(1)
val publisher = ZMQcontext.socket(ZMQ.PUB)
var count = 0
publisher.connect(s"tcp://127.0.0.1:16666")
while (!Thread.currentThread().isInterrupted) {
try {
println(s"PUBLISHER -> $count")
publisher.send(s"PUBLISHER -> $count")
count += 1
Thread.sleep(1000)
}
catch {
case e: Exception =>
println(e.getMessage)
publisher.disconnect(s"tcp://127.0.0.1:16666")
ZMQcontext.close()
}
}
}
}
I have a Subscriber Runnable:
class ZMQSubscriberRunnable1() extends Runnable {
override def run() {
println("STARTING SUBSCRIBER")
val ZMQcontext = ZMQ.context(1)
val subscriber = ZMQcontext.socket(ZMQ.SUB)
subscriber.subscribe("".getBytes)
subscriber.bind(s"tcp://127.0.0.1:16666")
while (!Thread.currentThread().isInterrupted) {
try {
println("waiting")
val mesg = new String(subscriber.recv(0))
println(s"SUBSCRIBER -> $mesg")
}
catch {
case e: Exception =>
println(e.getMessage)
subscriber.unbind("tcp://127.0.0.1:16666")
subscriber.close()
ZMQcontext.close()
}
}
}
}
My main code looks like this:
object Application extends App {
val zmqPUB = new ZMQPublisherRunnable
val zmqThreadPUB = new Thread(zmqPUB, "MY_PUB")
zmqThreadPUB.setDaemon(true)
zmqThreadPUB.start()
val zmqRunnable = new ZMQSubscriberRunnable1
val zmqThread = new Thread(zmqRunnable, "MY_TEST")
zmqThread.setDaemon(true)
zmqThread.start()
Thread.sleep(10000)
zmqThread.interrupt()
zmqThread.join()
Thread.sleep(2000)
val zmqRunnable_2 = new ZMQSubscriberRunnable1
val zmqThread_2 = new Thread(zmqRunnable_2, "MY_TEST_2")
zmqThread_2.setDaemon(true)
zmqThread_2.start()
Thread.sleep(10000)
zmqThread_2.interrupt()
zmqThread_2.join()
}
The first time I start the Subscriber, I'm able to receive all messages:
STARTING SUBSCRIBER
PUBLISHER -> 0
waiting
PUBLISHER -> 1
SUBSCRIBER -> PUBLISHER -> 1
waiting
PUBLISHER -> 2
SUBSCRIBER -> PUBLISHER -> 2
waiting
PUBLISHER -> 3
SUBSCRIBER -> PUBLISHER -> 3
waiting
...
Once I interrupt the Thread and start a new one from the same Runnable, I'm not able to read messages anymore. It is waiting forever
STARTING SUBSCRIBER
waiting
PUBLISHER -> 13
PUBLISHER -> 14
PUBLISHER -> 15
PUBLISHER -> 16
PUBLISHER -> 17
...
Any insights about what I'm doing wrong?
Thanks
JeroMQ is not Thread.interrupt safe.
To work around it you have to stop the ZMQContext before you call the Thread.interrupt
Instantiate the ZMQContext outside the Runnable
Pass the ZMQContext as an argument to the ZMQ Runnable (You can also use it is a global variable)
Call zmqContext.term()
Call zmqSubThread.interrupt()
Call zmqSubThread.join()
For more details take a look at: https://github.com/zeromq/jeromq/issues/116
My subscriber Runnable looks like:
class ZMQSubscriberRunnable(zmqContext:ZMQ.Context, port: Int, ip: String, topic: String) extends Runnable {
override def run() {
var contextTerminated = false
val subscriber = zmqContext.socket(ZMQ.SUB)
subscriber.subscribe(topic.getBytes)
subscriber.bind(s"tcp://$ip:$port")
while (!contextTerminated && !Thread.currentThread().isInterrupted) {
try {
println(new String(subscriber.recv(0)))
}
catch {
case e: ZMQException if e.getErrorCode == ZMQ.Error.ETERM.getCode =>
contextTerminated = true
subscriber.close()
case e: Exception =>
zmqContext.term()
subscriber.close()
}
}
}
}
To interrupt the Thread:
zmqContext.term()
zmqSubThread.interrupt()
zmqSubThread.join()
Here is the code:
import javafx.event
import javafx.event.EventHandler
import scalafx.application.{Platform, JFXApp}
import scalafx.application.JFXApp.PrimaryStage
import scalafx.event.ActionEvent
import scalafx.scene.Scene
import scalafx.scene.control.{Button, Label}
import scalafx.Includes._
import scalafx.scene.layout.{VBox, HBox}
object Blocking extends JFXApp {
val statusLbl = new Label("Not started...")
val startBtn = new Button("Start") {
onAction = (e: ActionEvent) => startTask
}
val exitBtn = new Button("Exit") {
onAction = (e: ActionEvent) => stage.close()
}
val buttonBox = new HBox(5, startBtn, exitBtn)
val vBox = new VBox(10, statusLbl, buttonBox)
def startTask = {
val backgroundThread = new Thread {
setDaemon(true)
override def run = {
runTask
}
}
backgroundThread.start()
}
def runTask = {
for(i <- 1 to 10) {
try {
val status = "Processing " + i + " of " + 10
Platform.runLater(() => {
statusLbl.text = status
})
println(status)
Thread.sleep(1000)
} catch {
case e: InterruptedException => e.printStackTrace()
}
}
}
stage = new PrimaryStage {
title = "Blocking"
scene = new Scene {
root = vBox
}
}
}
When the "start" button is pressed, the status label should be updated 10 times, but it is not. From the console you can see the background thread is actually updating the status, but these are not reflected in the UI. Why?
The problem is with the invocation of Platform.runLater. To make it work change it to:
Platform.runLater {
statusLbl.text = status
}
runLater[R](op: => R) takes as an argument a code block that returns a value of type R. You were passing a code block defining an anonymous function. runLater was creating a function, not executing it.
I want to make an actor sleep for a while, specifically it should decide whether to sleep itself depending on a condition:
class MyActor extends Actor {
def receive {
case "doWork" => doWork()
}
def doWork(): Unit = {
// doing some work
val condition = calculateCondition
if (condition) {
// sleep for 5 seconds
// Thread.sleep(5000)
}
}
}
I'm pretty much sure it's not a good thing to call Thread.sleep(5000) inside an actor and there should be another way. Therefore, how do I make it sleep?
I would look to do this using changes of state/behaviour for the Actor. Akka gives you a couple of means of doing this: you can implement a full-on state machine, or make use of context.become (and mix in akka.actor.Stash), and have the actor pass (scheduled) messages to itself. The former feels like overkill for this case, so here is how I would look to code it up:
import akka.actor._
import scala.concurrent.duration._
class MySleepyActor(duration: FiniteDuration = (5 seconds)) extends Actor with Stash {
import context._
override def preStart() { become(running) }
def receive = PartialFunction.empty
def running: Actor.Receive = {
case "doWork" =>
if (doWork()) {
scheduleReactivate
become(paused)
}
case "wakeUp" => // already awake
}
def paused: Actor.Receive = {
case "doWork" => stash()
case "wakeUp" =>
unstashAll()
become(running)
}
def scheduleReactivate: Unit = {
system.scheduler.scheduleOnce(duration, self, "wakeUp")
}
def doWork(): Boolean = {
// doing some work, then:
calculateCondition
}
}
Note: I have not tested this code! Should give you some ideas to work with, though.
I wrote logic for testing urls using threads.
This works good for less number of urls and failing with more than 400 urls to check .
class URL extends Thread{
def valid
def url
URL( url ) {
this.url = url
}
void run() {
try {
def connection = url.toURL().openConnection()
connection.setConnectTimeout(10000)
if(connection.responseCode == 200 ){
valid = Boolean.TRUE
}else{
valid = Boolean.FALSE
}
} catch ( Exception e ) {
valid = Boolean.FALSE
}
}
}
def threads = [];
urls.each { ur ->
def reader = new URL(ur)
reader.start()
threads.add(reader);
}
while (threads.size() > 0) {
for(int i =0; i < threads.size();i++) {
def tr = threads.get(i);
if (!tr.isAlive()) {
if(tr.valid == true){
threads.remove(i);
i--;
}else{
threads.remove(i);
i--;
}
}
}
Could any one please tell me how to optimize the logic and where i was going wrong .
thanks in advance.
Have you considered using the java.util.concurrent helpers? It allows multithreaded programming at a higher level of abstraction. There's a simple interface to run parallel tasks in a thread pool, which is easier to manage and tune than just creating n threads for n tasks and hoping for the best.
Your code then ends up looking something like this, where you can tune nThreads until you get the best performance:
import java.util.concurrent.*
def nThreads = 1000
def pool = Executors.newFixedThreadPool(nThreads)
urls.each { url ->
pool.submit(url)
}
def timeout = 60
pool.awaitTermination(timeout, TimeUnit.SECONDS)
Using ataylor's suggestion, and your code, I got to this:
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
class MyURL implements Runnable {
def valid
def url
void run() {
try {
url.toURL().openConnection().with {
connectTimeout = 10000
if( responseCode == 200 ) {
valid = true
}
else {
valid = false
}
disconnect()
}
}
catch( e ) {
valid = false
}
}
}
// A list of URLs to check
def urls = [ 'http://www.google.com',
'http://stackoverflow.com/questions/2720325/groovy-thread-for-urls',
'http://www.nonexistanturlfortesting.co.ch/whatever' ]
// How many threads to kick off
def nThreads = 3
def pool = Executors.newFixedThreadPool( nThreads )
// Construct a list of the URL objects we're running, submitted to the pool
def results = urls.inject( [] ) { list, url ->
def u = new MyURL( url:url )
pool.submit u
list << u
}
// Wait for the poolclose when all threads are completed
def timeout = 10
pool.shutdown()
pool.awaitTermination( timeout, TimeUnit.SECONDS )
// Print our results
results.each {
println "$it.url : $it.valid"
}
Which prints out this:
http://www.google.com : true
http://stackoverflow.com/questions/2720325/groovy-thread-for-urls : true
http://www.nonexistanturlfortesting.co.ch/whatever : false
I changed the classname to MyURL rather than URL as you had it, as it will more likely avoid problems when you start using the java.net.URL class