Carry the posts written by myself in the object-oriented curriculum discussion area since 2021 (last year), and make some revisions.
thank:
- BUAAWander Reply (this guy has become this year's OO teaching assistant)
- BUAA-Stargazer And supercalifragilistic Point out clerical errors in the code
This content was written when I studied OO course last year. The posted code is a little crude, which may not run completely, or it needs some modification, which is only used as a hint / guide for solving the problem.
The complete and operable timing input delivery tool has been reproduced and open-source this year GitHub , otherwise Coekjan A copy of open source Similar tools , can be used directly, and there is no need to introduce irrelevant code into the job. (please do not submit the source code or binary of the above auxiliary tools to the operation warehouse. If they are checked again, you will bear the consequences)
In this job, the requirement for input and output is real-time interaction. The input mode adopted is to release the input regularly through the console (stdin). Because the program is multi-threaded, in addition to the input, the running thread (elevator, etc.) will also output the content to the console in real time. Therefore, releasing the input regularly has become a small difficulty in the process of this job test. This post gives several debugging methods of regular input, and welcome the big guys to actively supplement!
Manual input
describe
Manually input the elevator request directly in the console.
realization
Slightly.
Pros and cons
Advantages: it is the most original and does not need additional tools as an aid.
Disadvantages: it is difficult to accurately control the time; It is difficult to put in more input; The input will be disturbed by the output (stdin and stdout share the same console)
Recommended or not: not recommended.
Input emitter + pipe
describe
Write a transmitter that can output regularly, and use the pipeline to transmit the input content to the elevator program.
realization
launcher
The transmitter reads the input information containing time from the standard input or file, and outputs the content to the standard output regularly according to the read time.
In this post, a relatively simple C language implementation is given:
// timeInput.c #include <stdio.h> #include <time.h> #ifdef WIN32 #include <windows.h> #define SLEEP_MS(x) Sleep((x)) #else #include <unistd.h> #define SLEEP_MS(x) usleep(1000*(x)) #endif char buf[1005]; long curMillis; int main() { long millis; while (scanf("%ld:", &millis) != EOF) { gets(buf); SLEEP_MS(millis - curMillis); puts(buf); fflush(stdout); curMillis = millis; } return 0; }
The corresponding input format is time: one line of content, where time is the number of milliseconds from the beginning to the release of the line of content. Example:
0:Start 1000:Now is 1 second 1500:Now is 1.5 second 3000:Now is 3 second
Operation method
Package the elevator program into jar (such as Elevator.jar) and run it on the command line:
timeInput.exe < input.txt | java -jar Elevator.jar
Pros and cons
Advantages: the command line is adopted, which is convenient for automatic test and batch test
Disadvantages: it is difficult to interrupt debugging without the IDEA environment.
Recommended or not: recommended for batch self-test or mutual test of local evaluation machine.
matters needing attention
come from BUAAWander Reply:
[Tips] the second method must be timely fflush, otherwise the pipeline will flow the content to the running jar only after all outputs are written
Scheduled task + pipeline flow
describe
The timed task of Java is adopted to directly read the input content with time stamp from the standard input, and deliver it to the standard input interface (elevator input) through pipeline flow according to the time
realization
Concept introduction
-
The Timer class in Java is used to add timing tasks, and input to the standard input interface through timing tasks.
-
Java provides a flow for mutual communication between threads - pipeline flow, which is divided into pipeline input stream and pipeline output stream. They usually appear in pairs (connected through the connect method) and are used in different threads respectively.
Realization idea
First, take a look at the source code of the official input package. You can see that it provides two construction methods:
public ElevatorInput() {...} // Adopt system In standard input stream public ElevatorInput(InputStream inputStream) {...} // Specify your own input stream
In order to realize the controllable delivery of content to the input interface, the system is no longer used when instantiating the input interface In, but uses a PipedInputStream. At the same time, in order to make the pipeline input flow work normally, you also need to instantiate a paired pipeline output flow and connect them.
Pipeline flow initialization:
// Instantiate a pair of pipe flows PipedOutputStream myPipeOut = new PipedOutputStream(); PipedInputStream myPipeIn = new PipedInputStream(); // Connect the two, and the connect method of PipedOutputStream will throw IOException try { myPipeOut.connect(myPipeIn); } catch (IOException e) { throw new AssertionError(e); // Never happen }
Initialization of official input package:
ElevatorInput elevatorInput; if (DEBUG) { // Debugging switch, be sure to turn it off when submitting evaluation! elevatorInput = new ElevatorInput(myPipeIn); } else { elevatorInput = new ElevatorInput(System.in); }
Then we can use the pipeline output stream object myPipeOut to deliver the input content to the official package.
In order to avoid the trouble of real-time interaction, we can prepare the input content containing time information in advance, then open a thread to read the prepared input content, analyze the time information, and add a scheduled task through Timer's schedule method. The content of the scheduled task is to output the input content to the pipeline flow.
public class DebugInput implements Runnable { private final OutputStream outputStream; public DebugInput(OutputStream outputStream) { this.outputStream = outputStream; } @Override public void run() { Scanner scanner = new Scanner(System.in); Timer timer = new Timer(); // Initialize a timer long currentMillis = System.currentTimeMillis(); long maxMillis = 0; // Record the time of the last entry while (scanner.hasNext()) { long millis = scanner.nextLong(); // Read time first String input = scanner.next(); // Read the input (no spaces) maxMillis = millis; // Update maxMillis timer.schedule(new TimerTask() { // Create scheduled task @Override public void run() { try { outputStream.write(input.getBytes()); outputStream.write(0x0a); // Line feed outputStream.flush(); // force refresh } catch (IOException e) { throw new AssertionError(e); } } }, new Date(currentMillis + millis)); } // Finally, don't forget to turn off the pipeline flow and turn off the timer to add the last scheduled task timer.schedule(new TimerTask() { @Override public void run() { try { outputStream.close(); } catch (IOException e) { throw new AssertionError(e); } timer.cancel(); // Turn off the timer. If this sentence is not added, the timer may wait indefinitely } }, new Date(currentMillis + maxMillis + 1)); } }
Note: the above code reads the input information containing time from stdin. In order to facilitate debugging, you can store the input content in a file and configure Redirect Input in IDEA.
Input format: input content in milliseconds (the input content cannot have spaces)
0 Random 1000 1-FROM-1-TO-2 1500 2-FROM-2-TO-1
Start the thread of timed delivery input just written:
new Thread(new DebugInput(myPipeOut)).start();
Other points
Using this method for debugging, it is recommended to add a debugging switch, which can be turned on during local debugging and turned off when submitting evaluation. There is no need to modify the code. (be sure to turn off this debugging switch in the submitted code)
Pros and cons
Advantages: it is convenient to debug the break point in the IDEA, and it can also be packaged into a jar to directly redirect the standard input for testing.
Disadvantages: you need to add classes in the project, which is troublesome to implement.
Recommended: recommended during local debugging or self-test of local evaluation machine.
Method improvement
The input format given in the post is inconsistent with the time format of the actual example. Students who adopt this method can consider how to support the time format given by the example, for example:
[0.0]Random [1.0]1-FROM-1-TO-2 [2.5]2-FROM-5-TO-1
(tip: modify 16 to 17 lines of code. You can use the preview homework and the regular expression learned in unit 1 to extract the time in brackets and the input after brackets)