How do we run multiple functions concurrently in Scala? - multithreading

This is a scala code I'm trying to write for processing a function multiple times concurrently with two different parameters. However, I notice that the functions are being executed one by one and not both at same time.
class Method1 extends Thread {
override def run(): Unit ={
println("Hello, Current running is Thread No. " + Thread.currentThread().getName )
Function("Parameter 1")
Function("Parameter 2")
}
}
object Obj extends App {
for (x <- 1 to 4){
val th1 = new Method1()
th1.setName(x.toString)
th1.start()
}
}
val a = Array("Justanormalarray")
Obj.main(a)
How to achieve this? Sorry for being dumb but all tutorials I seen only explains a very basic level that multithreading can be achieved by extending thread class or by using runnable interface, but doesn't seem to clear this up (i.e. how to actually execute multiple stuff at same time)

Related

Writing tests to use Kafka consumer in multi-threading environment

I am trying to create a kafka consumer in a separate thread which consumes data from kafka topic. For this, I have extended ShutdownableThread abstract class and provided implementation for doWork method. My code is like this -
abstract class MyConsumer(topic: String) extends ShutdownableThread(topic) {
val props: Properties = ???
private val consumer = new KafkaConsumer[String, String](props)
consumer.subscribe(List(topic).asJava)
def process(value: String): Unit // Abstract method defining what to do with each record
override def doWork(): Unit = {
for (record <- consumer.poll(Duration.ofMillis(1000)).asScala)
process(record.value())
}
}
Now in my tests, I create consumer providing implementation of process() method which just mutates a variable and then call start() method of it to start the thread.
var mutVar = "initial_value"
val consumer = new MyConsumer("test_topic") {
override def process(value: String): Unit = mutVar = "updated_value"
}
consumer.start()
assert(mutVar === "updated_value")
The Consumer does consume the message from the kafka but it does not update it before the test finishes and hence the test fails. So, I tried to put the main thread on sleep. But it throws ConcurrentModificationException exception with the message - KafkaConsumer is not safe for multi-threaded access
Any idea what is wrong with my approach ? Thanks in advance.
Had to put main thread to sleep for few seconds to allow consumer to consume message from kafka topic and store it in the mutable variable. Added - Thread.sleep(5000) after starting the consumer.

Jenkins pipeline script - Thread programming

I am trying to create multiple threads in a jenkins pipeline script. So, I took simple example as below. But it not working. Could you please let me know?
In the below example, jobMap contains a key as a string and value as List of Strings. When I just display the list, the values printed properly, but when I used 3 different ways to create threads and thus to display, it is not working.
for ( item in jobMap )
{
def jobList = jobMap.get(item.key);
**// The following loop is printing the values**
for (jobb in jobList)
{
echo "${jobb}"
}
// Thread Implementation1:
Thread.start
{
for (jobb in jobList)
{
echo "${jobb}"
}
}
// Thread Implementation2:
def t = new Thread({ echo 'hello' } as Runnable)
t.start() ;
t.join();
// Thread Implementation3:
t1 = new Thread( new TestMultiThreadSleep(jobList));
t1.start();
}
class TestMultiThreadSleep implements Runnable {
String jobs;
public TestMultiThreadSleep(List jobs) {
this.jobs = jobs;
}
#Override
public void run()
{
echo "coming here"
for (jobb in jobs)
{
echo "${jobb}"
}
}
}
Jenkins has special step - parallel(). In this step you can build another jobs or call Pipeline code.
It's best to think of Pipeline code as a dialect or subset of Groovy.
The CPS transformer ("continuation-passing style") in the workflow script engine turns the Groovy code into something that can be interpreted in a serialized form, passed between different JVMs, etc.
You can probably imagine that this will not work at all well with threads.
If you need threads, you'll have to work within a #NonCPS annotated class or function. This class or function must not call any CPS groovy code - so it can't invoke closures, access the workflow script context, etc.
That's why using the parallel step is preferable.

Groovy multi tasking

I am trying the execute the below code in which four threads are running.
Each thread trying to add the one character to mylist. After each run, there should be 4 elements in the list in any order. But, when this code is run in jenkin console, getting each time different number of elements. i.e, [A, B, Null], [C,null,D],[A,B,C,D].
It seem like some synchronization issue due to multi tasking. I have tried adding method add element to list using synchronize keyword but that didn't help.
class Globals {
static def mylist=[]
}
class TestMultiThreadExecution implements Runnable
{
String name;
public TestMultiThreadExecution(String name) {
this.name = name;
}
//#Override
public void run() {
println "${name} Step 1"
Globals.mylist.push("${name}")
}
}
Globals.mylist.clear()
Thread thread1 = new Thread(new TestMultiThreadExecution("A"));
thread1.start();
Thread thread2 = new Thread(new TestMultiThreadExecution("B"));
thread2.start();
Thread thread3 = new Thread(new TestMultiThreadExecution("C"));
thread3.start();
Thread thread4 = new Thread(new TestMultiThreadExecution("D"));
thread4.start();
thread1.join();
thread2.join();
thread3.join();
thread4.join();
println Globals.mylist
It is because, list is being concurrently accessed and modified by 4 threads.
You can fix it by changing list type to CopyOnWriteArrayList as shown below.
So, the only change in the above code is to change list type in the Globals class. Here is the changed code snippet.
import java.util.concurrent.CopyOnWriteArrayList
class Globals {
static def mylist = [] as CopyOnWriteArrayList
}
By the, it would be lot easier in groovy to deal with threads. May be you can refer a sample

How to make this simple Groovy code concurrent/multi-threaded?

I have a very simple groovy script that works through a JSON and performs some actions. Since there are no dependencies between the JSON records and actions I was hoping I could speed up the execution a bit. Given this codeā€¦
def recordJSON = new JsonSlurper().parseText(myFile.text)
recordJSON.each{
do stuff here
}
Is there a way to thread the execution or perform them in parallel? I've done a bit of reading on the topic, but I'm a casual coder and they seem to be a bit over my head.
The easiest is to use GPars which is part of groovy:
import static groovyx.gpars.GParsPool.withPool
withPool {
recordJSON.eachParallel {
do stuff here
}
}
If you are more comfortable with Java thread constructions, this might be of interest (Groovy offers all of the usual Java goodies, with less boilerplate):
import java.util.concurrent.*
import groovy.json.*
class MyTask implements Runnable {
File file
void run() {
def recordJSON = new JsonSlurper().parseText(file.text)
println "do stuff here ${file.name}"
}
}
// ------ main
def pool = Executors.newCachedThreadPool()
(1..6).each {
def f = new File("f${it}.json")
pool.submit(new MyTask(file: f))
}

How to understand "new {}" syntax in Scala?

I am learning Scala multi-thread programming, and write a simple program through referring a tutorial:
object ThreadSleep extends App {
def thread(body: =>Unit): Thread = {
val t = new Thread {
override def run() = body
}
t.start()
t
}
val t = thread{println("New Therad")}
t.join
}
I can't understand why use {} in new Thread {} statement. I think it should be new Thread or new Thread(). How can I understand this syntax?
This question is not completely duplicated to this one, because the point of my question is about the syntax of "new {}".
This is a shortcut for
new Thread() { ... }
This is called anonymous class and it works just like in JAVA:
You are here creating a new thread, with an overriden run method. This is useful because you don't have to create a special class if you only use it once.
Needs confirmation but you can override, add, redefine every method or attribute you want.
See here for more details: https://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html
By writing new Thread{} your creating an anonymous subclass of Thread where you're overriding the run method. Normally, you'd prefer to create a subclass of Runnable and create a thread with it instead of subclassing Thread
val r = new Runnable{ override def run { body } }
new Thread(r).start
This is usually sematincally more correct, since you'd want to subclass Thread only if you were specializing the Thread class more, for example with an AbortableThread. If you just want to run a task on a thread, the Runnable approach is more adequate.

Resources