简体   繁体   English

如何在创建类时启动线程并多次使用(重新)执行一个方法

[英]How to start a thread at creation time of a class and (re)use it to execute a method multiple times

I am trying to solve an exercise while studying for my next exam. 我正在为下一次考试学习而尝试解决一个练习。 This is the question 这是问题

Use Java to implement a MsgBatcher class that holds a (finite) set of messages and sends them, on request, in batch. 使用Java来实现MsgBatcher类,该类保存(有限)消息集,并根据请求批量发送。 Suppose we have a Message class with a method void send(). 假设我们有一个Message类,其方法为void send()。 MsgBatcher provides a method void enqueue(Message) to add a new message to the batch. MsgBatcher提供了一个方法void enqueue(Message)将新消息添加到批处理中。 It suspends the caller if the MsgBatcher is full (the maximum number of messages that can be enqueued is provided in the MsgBatcher constructor). 如果MsgBatcher已满(在MsgBatcher构造函数中提供了可以排队的最大消息数),它将挂起调用方。 A method void sendAll() is also provided to send all messages enqueued up to that moment (it empties the MsgBatcher). 还提供了一个方法void sendAll()来发送该时刻之前排队的所有消息(它清空MsgBatcher)。 Organize synchronization that will take care of the fact that sending a message may take a long time. 组织同步,这将解决发送消息可能会花费很长时间的事实。 Optional: implement the sendAll method so that the sending is performed asynchronously wrt the caller (ie, in a separate thread, which should be started at MsgBatcher creation time and reused for each sending). 可选:实现sendAll方法,以便在调用方时异步执行发送(即在单独的线程中执行,该线程应在MsgBatcher创建时启动,并在每次发送时重用)。

So far i have written this 到目前为止,我已经写了这个

import java.util.ArrayList;

public class MsgBatcher {

    public ArrayList<Message> batch = new ArrayList<Message>();
    int maxSpaces;

    public void MsgBatcher(int max){
        this.maxSpaces= max;
    }
    public synchronized void enqueue(Message m) throws InterruptedException{
        while(batch.size() == maxSpaces) wait();
        this.batch.add(m);
    }
    public void sendAll(){
        ArrayList<Message> toSend = new ArrayList<Message>();
        toSend.addAll(batch);
        batch.clear(); //in this way i can accept other messages while sending the others

        for (Message m : toSend){
            m.send();
        }
        batch.clear();
    }
}   

and since the Message class is not really important i have written just a few lines to emulate the asked behaviour 由于Message类不是很重要,所以我只写了几行来模拟所要求的行为

public class Message {

 public void send(){
     System.out.println("Sending");
     try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
     System.out.println("Sent");
 }
}

what i do not understand is how to deal with 我不明白的是如何应对

Organize synchronization that will take care of the fact that sending a message may take a long time. 组织同步,这将解决发送消息可能会花费很长时间的事实。

and especially with 特别是

Optional: implement the sendAll method so that the sending is performed asynchronously wrt the caller (ie, in a separate thread, which should be started at MsgBatcher creation time and reused for each sending). 可选:实现sendAll方法,以便在调用方时异步执行发送(即在单独的线程中执行,该线程应在MsgBatcher创建时启动,并在每次发送时重用)。

as per title of this question 按照这个问题的标题

I know i should ask the Professor, and i have already sent him an email, but he did not answer. 我知道我应该问教授,我已经给他发了电子邮件,但他没有回答。 Thanks for your help! 谢谢你的帮助!

I think you were preparing the exam Middleware technologies for dist sys at PoliMi. 我认为您正在为PoliMi的dist sys准备考试中间件技术。

I'm doing as well and I found your question because I'm doing the same exercise. 我也做得很好,我找到了你的问题,因为我正在做同样的练习。 This is my solution and it seems to work well. 这是我的解决方案,它似乎运行良好。

I posted it, even if you don't probably need it anymore, in case someone else will need while preparing this exam. 我发布了它,即使您可能不再需要它了,以防万一其他人在准备此考试时也需要它。

import java.util.ArrayList;

public class TestThread extends Thread{

private String name;
private MsgBatcher msgBatcher;

public TestThread(String name, MsgBatcher msgBatcher){
    this.name = name;
    this.msgBatcher = msgBatcher;
}

/**
 * Each thread tries to add 10 messages.
 */
public void run(){
    for(int i = 0; i < 10; i++){
        Message msg = new Message("Thread " + this.name + " | i: " + i);
        try{
            System.out.println("[T] Thread " + this.name + " Adding " + i);
            this.msgBatcher.enqueue(msg);
            System.out.println("[T] Thread " + this.name + " Added " + i);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

public static void main(String[] args){
    MsgBatcher msgBatcher = new MsgBatcher(10);
    TestThread t1 = new TestThread("1", msgBatcher);
    TestThread t2 = new TestThread("2", msgBatcher);

    t1.start();
    t2.start();

    try{
        //After 3 seconds we try to send the first batch
        Thread.sleep(3000);
        msgBatcher.sendAll();
    }catch (Exception e){
        e.printStackTrace();
    }

}
}

class MsgSender extends Thread{

private ArrayList<Message> toSend;

public MsgSender(){
    this.toSend = new ArrayList<Message>();
}

public void run(){
    while(true){
        synchronized (this){
            try{
                System.out.println("[MS] Starting run.");
                while (this.toSend.size() == 0){
                    System.out.println("[MS] Waiting for messages." + this.toSend.size());
                    wait();
                }

                System.out.println("[MS] Messages ready to be sent.");

                for(Message msg: this.toSend){
                    msg.send();
                }

                this.toSend.clear();

                System.out.println("[MS] Messages sent.");

                notifyAll();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

public synchronized void addMsgs(ArrayList<Message> toSend){
    synchronized (this){
        try{
            System.out.println("[MS] Adding messages.");
            while (this.toSend.size() != 0){
                System.out.println("[MS] Adding messages. Waiting toSend to become empty");
                wait();
            }

            this.toSend = toSend;

            System.out.println("[MS] Messages added. Notifying the run."  + this.toSend.size());

            notifyAll();
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    this.toSend = toSend;

    notify();
}
}

class MsgBatcher{

private int size;
private ArrayList<Message> queue;
private MsgSender msgSender;

public MsgBatcher(int size){
    this.size = size;
    this.queue = new ArrayList<Message>(this.size);
    this.msgSender = new MsgSender();
    this.msgSender.start();
    try{
        //wait enough time to be sure the msgSender thread is ready
        Thread.sleep(3000);
    }catch (Exception e){
        e.printStackTrace();
    }
}

public synchronized void enqueue(Message msg) throws InterruptedException{
    System.out.println("[MB] size: " + this.queue.size());
    while(this.queue.size() == this.size){
        wait();
    }

    this.queue.add(msg);

    notifyAll();
}

public synchronized void sendAll(){
    System.out.println("Sending all messages");

    ArrayList<Message> toSend = new ArrayList<Message>();
    toSend.addAll(this.queue);

    this.msgSender.addMsgs(toSend);

    this.queue.clear();

    notifyAll();
}
}

class Message {

private String text;

public Message(String text){
    this.text = text;
}

public void send(){
    System.out.println("[M] Sending: " + this.text);
    try{
        Thread.sleep(1000);
    }catch (Exception e){
        e.printStackTrace();
    }
    System.out.println("[M] Sent: " + this.text);
}
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM