In Go, multithreading is one of the main features, respectively, the ability to convert Java code using multithreading into Go code automatically, which uses channels, is very important.
I found a suitable example of ProducerConsumerExample from Oracle there:
Oracle sample, where the Drop class is a candidate for conversion to Go using channels.
But, now I give an intermediate result without channels.
Also, I read the opinion that the conversion of Java code where annotations are used in runtime is impossible. It is necessary to investigate the problem and try to understand if it is possible to solve it somehow. Before transferring a project from the status of "possibility of achievement" to the status of "prototype", it is necessary to see what can be done with these problems in relation to annotations.
Java code:
package com.builder.start.here;
import java.util.Random;
public class RunMeDrop {
public static void main(String[] args) {
Drop drop = new Drop();
(new Thread(new Producer(drop))).start();
(new Thread(new Consumer(drop))).start();
}
}
class Drop {
// Message sent from producer
// to consumer.
private String message;
// True if consumer should wait
// for producer to send message,
// false if producer should wait for
// consumer to retrieve message.
private boolean empty = true;
public synchronized String take() {
// Wait until message is
// available.
while (empty) {
try {
wait();
} catch (InterruptedException e) {}
}
// Toggle status.
empty = true;
// Notify producer that
// status has changed.
notifyAll();
return message;
}
public synchronized void put(String message) {
// Wait until message has
// been retrieved.
while (!empty) {
try {
wait();
} catch (InterruptedException e) {}
}
// Toggle status.
empty = false;
// Store message.
this.message = message;
// Notify consumer that status
// has changed.
notifyAll();
}
}
class Consumer implements Runnable {
private Drop drop;
public Consumer(Drop drop) {
this.drop = drop;
}
public void run() {
Random random = new Random();
for (
String message = drop.take();
! message.equals("DONE");
message = drop.take()) {
System.out.format(
"MESSAGE RECEIVED: %s%n", message);
try {
Thread.sleep(random.nextInt(5000));
} catch (InterruptedException e) {}
}
}
}
class Producer implements Runnable {
private Drop drop;
public Producer(Drop drop) {
this.drop = drop;
}
public void run() {
String importantInfo[] = {
"Mares eat oats",
"Does eat oats",
"Little lambs eat ivy",
"A kid will eat ivy too"
};
Random random = new Random();
for (int i = 0; i < importantInfo.length; i++) {
drop.put(importantInfo[i]);
try {
Thread.sleep(random.nextInt(5000));
} catch (InterruptedException e) {}
}
drop.put("DONE");
}
}
Converter gave out:
package main
import (
"fmt"
"math/rand"
"os"
"sync"
"time"
)
type RunMe struct{}
func NewRunMe() *RunMe {
var runMe RunMe = RunMe{}
return &runMe
}
func main() {
var args []string = os.Args
var rm *RunMe = NewRunMe()
rm.RunMe_main(&args)
}
/** generated method **/
func (runMe *RunMe) RunMe_main(args *[]string) {
wg := &sync.WaitGroup{}
var drop *Drop = NewDrop()
wg.Add(1)
go (&Thread{NewProducer(drop)}).run(wg)
wg.Add(1)
go (&Thread{NewConsumer(drop)}).run(wg)
wg.Wait()
}
type Drop struct {
/** generated field */
cond *sync.Cond
message *string
empty *bool
}
func NewDrop() *Drop {
var drop Drop = Drop{}
drop.cond = sync.NewCond(&sync.Mutex{})
empty := true
drop.empty = &empty
return &drop
}
func (drop *Drop) take() string {
drop.cond.L.Lock()
for *drop.empty {
drop.cond.Wait()
}
*drop.empty = true
drop.cond.L.Unlock()
drop.cond.Broadcast()
return *drop.message
}
func (drop *Drop) put(message *string) {
drop.cond.L.Lock()
for !*drop.empty {
drop.cond.Wait()
}
*drop.empty = false
drop.message = message
drop.cond.L.Unlock()
drop.cond.Broadcast()
}
type Consumer struct {
drop *Drop
}
func NewConsumer(drop *Drop) *Consumer {
var consumer Consumer = Consumer{drop}
return &consumer
}
func (consumer *Consumer) run(wg *sync.WaitGroup) {
defer wg.Done()
var random *Random = NewRandom()
for message := consumer.drop.take();
message != "DONE";
message = consumer.drop.take() {
fmt.Printf("MESSAGE RECEIVED: %s\n", message)
time.Sleep(random.nextInt(5000))
}
}
type Producer struct {
drop *Drop
}
func NewProducer(drop *Drop) *Producer {
var producer Producer = Producer{drop}
return &producer
}
func (producer *Producer) run(wg *sync.WaitGroup) {
defer wg.Done()
var importantInfo [4]string = [4]string{
"Mares eat oats",
"Does eat oats",
"Little lambs eat ivy",
"A kid will eat ivy too",
}
var random *Random = NewRandom()
for i := 0; i < len(importantInfo); i++ {
producer.drop.put(&importantInfo[i])
time.Sleep(random.nextInt(5000))
}
s := "DONE"
producer.drop.put(&s)
}
type Random struct{}
func NewRandom() *Random {
var random Random = Random{}
return &random
}
func (r *Random) nextInt(n int) time.Duration {
return time.Duration(rand.Intn(n))
}
type Thread struct {
Runnable
}
func (t *Thread) run(wg *sync.WaitGroup) {
t.Runnable.run(wg)
}
type Runnable interface {
run(wg *sync.WaitGroup)
}
The Go Playground, you can run code there:
Go Playground.
Thank you to all very much.
четверг, 28 апреля 2022 г. в 19:08:51 UTC+3, alex-coder: