讲解:COMP0008、java、VERSION2、swingW
COMP0008 Written Java Coursework (2019/20)NOTE: Your final Moodle submission will consist of a number of parts:1. Three different versions of the “ConwaysGameOfLife.java” file after different modifications called: “ConwaysGameOfLife_VERSION1.java”, “ConwaysGameOfLife_VERSION2.java”, “ConwaysGameOfLife_VERSION3.java”.(Thus you should only modify this file and not create other Java files.)2. A PDF file giving answers to the questions below (given with bold stars). You can write this description using Word or Latex - as long as you submit a PDF version in the end.Getting going ...Take your favourite Java IDE and install:Conway’s Game of Life From the github:https://github.com/Burke9077/Conway-s-Game-of-Life.git(You should be familiar with how to do this.)This is quite a popular version of the game mentioned in a number of websites … but we are going to analyse its faults and try to improve its structure … in particular focusing on concurrency.Build the system, run it and play around with the GUI to get a feel for how it works.You should take copies of your Java files after each of these tasks to be submitted to Moodle. [Also this will enable you to roll back to a previous working version if revisions all go horribly wrong! Although ideally you would be using a revision control system like git.]Task 1: To get you familiar with the code.Choose the File > Options menu to set the rate of the game at 20 frames per second.Choose the Game > Autofill menu item and select 40% random tiles to fill. Now start the game running … and wait.Eventually (after a number of minutes) … it will crash with:---Exception in thread Thread-0 java.lang.StackOverflowErrorat java.desktop/java.awt.event.InvocationEvent.(InvocationEvent.java:286)at java.desktop/java.awt.event.InvocationEvent.(InvocationEvent.java:172)at java.desktop/javax.swing.RepaintManager.scheduleProcessingRunnable(RepaintManager.java:1485)at java.desktop/javax.swing.RepaintManager.addDirtyRegion0(RepaintManager.java:474)at java.desktop/javax.swing.RepaintManager.addDirtyRegion(RepaintManager.java:496)at java.desktop/javax.swing.JComponent.repaint(JComponent.java:4836)at java.desktop/java.awt.Component.repaint(Component.java:3352)at ConwaysGameOfLife$GameBoard.run(ConwaysGameOfLife.java:311)at ConwaysGameOfLife$GameBoard.run(ConwaysGameOfLife.java:314)… and then it repeats this same line hundreds of times !!!Now you might be tempted to post out a question to “StackOverflow” to resolve this StackOverflowException! But avoid doing this since I think you can fix it yourself with only 3 line of code being changed!Task 1 is to fix this bug and get familiar with how the code is working. You may not have done any Java Swing programming before … so I’m going to describe how the system generally works below but you may need to look up some further information describing how Swing works.But before reading below, have a look through the code and try to work out how it is working (it is all in a single file “ConwaysGameOfLife.java”).The system uses the Java Swing toolkit for the graphical elements. The “main” method essentially sets up a “JFrame game = new ConwaysGameOfLife();” which is the main public class in this file. A JFrame is the main graphical interface for the game. The main method then sets up some settings before doing a “game.setVisible(true)” to make the GUI visible.The constructor of this class sets up all the graphical Swing components of the GUI interface such as menu items, with “action listeners” referencing the class itself. The “actionPerformed” method gets called when a menu item is selected. This looks up the source of different events (such as “ae.getSource().equals(mi_game_play)” and then calls the appropriate method “setGameBeingPlayed(true);”This method then does:public void setGameBeingPlayed(boolean isBeingPlayed) {if (isBeingPlayed) {mi_game_play.setEnabled(false);mi_game_stop.setEnabled(true);game = new Thread(gb_gameBoard);game.start();} else {mi_game_play.setEnabled(true);mi_game_stop.setEnabled(false);game.interrupt();} }The first lines enable and disable particular menu items (mi_game_start and mi_game_stop menu items). But the key lines are the creation of a new “game” thread and starting this. And also calling an interrupt on it to stop this game thread.The thread is created from the gb_gameBoard which you will see is created at the end of the constructor and then added into the JFrame. This is actually the graphical game board itself which is added onto the JFrame and it gets repainted using its paint() method to draw the current position of “live squares” on the board.The GameBoard is a private class and it probably has too many responsibilities:private class GameBoard extends JPanel implements ComponentListener, MouseListener, MouseMotionListener, Runnable {It extends JPanel which means it is a Swing graphical panel (i.e. draws the board). It also implements different listeners which means it can respond to mouse events and it also implements a Runnable which is the game thread itself. So the GUI event thread may be running through this class, for instance clicking a mouse will cause the “mouseReleased()” method to be called by the GUI event thread. Changing the interface may cause the GUI thread to call the paintComponent() or componentResized() methods. In addition there is the run() method which clearly implements another user threads in this class. Look through this run() method to see what it is doing.Now what could be causing the StackOverflowError above?Identify the issue and restructure the code so that it no longer throws this error. This will only require a few lines of code to be changed. Ensure the interrupt mechanism to stop the game still works as well though.After fixing this bug … you should be able to run the game for a long time without having a StackOverflowError resulting. *** QUESTION 1: Describe what caused this bug and how you fixed it.*** Take a copy of your Java code and label it “ConwaysGameOfLife_VERSION1.java”Task 2: Getting into trouble with concurrency.It should be clear now that there are two threads running through the GameBoard class. A GUI thread which is painting the squares (and also changing them on mouse events) together with changing other aspects of the boards (for instance when resizing the board). Also there is a user thread that is calculating how squares change for the next step in the game. It seems the GameBoard class is responsible for too much and it’s sure to end in disaster!The GUI thread repaints the board by calling:public void paintComponent(Graphics g) {within the GameBoard class.You may notice the lines:try {for (Point newPoint : point) {// Draw new pointg.setColor(Color.blue);g.fillRect(BLOCK_SIZE + (BLOCK_SIZE*newPoint.x), BLOCK_SIZE + (BLOCK_SIZE*newPoint.y), BLOCK_SIZE, BLOCK_SIZE);}} catch (ConcurrentModificationException cme) {}The catching (and then ignoring) of the “ConcurrentModificationException” sort of indicates that we have a concurrency issue here! Add a “System.out.println(“CONCURRENCY ISSUE !!!”)” into the code to see if we ever get this exception actually being thrown:} catch (ConcurrentModificationException cme) {System.out.println(CONCURRENCY EXCEPTION !!!);}Running at 20 frames per second with 40% random squares … try changing the board by clicking on it … or resizing the board … minimizing it and maximizing it (causing the repaint method to be called). What you are trying to do is cause the “CONCURRENCY EXCEPTION !!!” message to be displayed. It isn’t easy since it requires the GUI thread and the game tCOMP0008作业代做、代写java程序语言作业、代写VERSION2实验作业、代做swing作业 代写Web开发|代hread to collide in terms of accessing or modifying the game squares. But I can produce multiple concurrency exceptions when drawing squares over the board with the mouse button pressed while the game is running:---/usr/lib/jvm/java-1.11.0-openjdk-amd64/bin/java -javaagent:/home/ucackxb/software/idea?IC-183.4588.61/lib/idea_rt.jar=39515:/home/ucackxb/software/idea-IC-183.4588.61/bin -Dfile.encoding=UTF-8 -classpath /home/ucackxb/COURSES/COMP0008/Conway-s?Game-of-Life_version2/out/production/Conway-s-Game-of-Life ConwaysGameOfLifeCONCURRENCY EXCEPTION !!!CONCURRENCY EXCEPTION !!!CONCURRENCY EXCEPTION !!!CONCURRENCY EXCEPTION !!!---But you can actually get worse than this. By very quickly decreasing the size of the board while it is being recalculated … you can get the user thread crashing out with an ArrayIndexOutofBoundsException:---/usr/lib/jvm/java-1.11.0-openjdk-amd64/bin/java -javaagent:/home/ucackxb/software/idea?IC-183.4588.61/lib/idea_rt.jar=46389:/home/ucackxb/software/idea-IC-183.4588.61/bin -Dfile.encoding=UTF-8 -classpath /home/ucackxb/COURSES/COMP0008/Conway-s?Game-of-Life_version2/out/production/Conway-s-Game-of-Life ConwaysGameOfLifeCONCURRENCY EXCEPTION !!!CONCURRENCY EXCEPTION !!!Exception in thread Thread-0 java.lang.ArrayIndexOutOfBoundsException: 47at ConwaysGameOfLife$GameBoard.run(ConwaysGameOfLife.java:285)at java.base/java.lang.Thread.run(Thread.java:844)---(Make the board the size of the complete screen and start running it with 40% random squares at 20 frames per second. Then press the icon to size it back to its default window size … this almost guarantees it will throw this exception!)Adjusting the graphics while it is running can also cause the GUI “AWT” thread to crash out with a NullPointer exception which is most likely due to concurrency issues as well (and then the GUI has crashed even though the rest of the program carries on running):---/usr/lib/jvm/java-1.11.0-openjdk-amd64/bin/java -javaagent:/home/ucackxb/software/idea?IC-183.4588.61/lib/idea_rt.jar=32797:/home/ucackxb/software/idea-IC-183.4588.61/bin -Dfile.encoding=UTF-8 -classpath /home/ucackxb/COURSES/COMP0008/Conway-s?Game-of-Life_version2/out/production/Conway-s-Game-of-Life ConwaysGameOfLifeCONCURRENCY EXCEPTION !!!Exception in thread AWT-EventQueue-0 java.lang.NullPointerExceptionat ConwaysGameOfLife$GameBoard.paintComponent(ConwaysGameOfLife.java:229)at java.desktop/javax.swing.Jcomponent.paint(JComponent.java:1074)---For something that looks like it “roughly works” … it’s amazing how fragile it really is due to not considering concurrency issues properly! (In fact putting in code that ignores concurrency issues!)Your second task it to fix these concurrency issues! Actually it may seem daunting but it really comes down to identifying the shared state that is being modified by both threads and ensuring that it is being operated on safely.It may be useful to understand how ConcurrentModificationExceptions arise. The Brian Goetz book explains this in Section 5.1.2 on page 82 (although it would be worthwhile reading from the start of Chapter 5 on page 79 to Section 5.3 Blocking Queues and the producer-consumer pattern on page 87 to get context for this and also to understand the CopyOnWriteArrayList in Section 5.2.3 which we will be using).It may also be useful to read Chapter 9 GUI Applications (pages 189-202) of the Brian Goetz book to get familiar with both Swing GUIs and how threads work in the GUI subsystem.Change the ArrayList used currently for the “state” of the GameBoard to using the concurrent CopyOnWriteArrayList object. Can you now make the system crash by adding points and resizing the window?*** QUESTION 2: Explain what is the key difference in how the CopyOnWriteArrayList behaves compared to a normal ArrayList which has probably made all these concurrency issues disappear (be specific about how a particular mechanism used in the code works differently with these two classes).*** QUESTION 3: What could be a disadvantage of using CopyOnWriteArrayList here instead of a normal Arraylist? (Assuming we weren’t worried about the concurrency issues!)*** Take a copy of your Java code and label it “ConwaysGameOfLife_VERSION2.java”Task 3: Speed it up challenge!This part is more challenging and the instructions are less detailed. So you will have to work out how certain aspects need to be structured yourself and also worry about whether your code is thread safe.We first want to calculate the time it takes to do 100,000 cycles of the board without any sleeping involved.1. Comment out the sleep statement in the run() method so it runs at maximum speed.2. Change the structure within the run() method so that it does 100,000 cycles of the board and then finishes automatically.3. Add “Date” objects (or similar) so that you can print out the time it takes to do the 100,000 cycles in milliseconds.*** QUESTION 4: Do five runs and write down the different times your system takes to do 100,000 cycles of the game of life (these will not all be shown on the screen due to not having any sleep time in the code).Now you probably have a multicore processor and the current system is only making use of a single core since it is running a single thread for all the calculations.We are going to restructure the code so that a number of threads each do the calculation of one column of the shared board object. We will used the Executors.newFixedThreadPool(4) to carry out the tasks (where we change the number of threads in the pool to see how it affects the overall speed).Create a FixedThreadPool executor at the top of the GameBoard class with initially 4 threads in the pool.The restructuring will involve the current run() method creating a new Runnable object, which you should call “BladeRunner”, for each “i” that it iterates over. Each “BladeRunner” object will then do the calculation for that column of the boolean[][] gameBoard –essentially doing the code within the central “i” loop of the current run() method. Each of these “BladeRunner” objects will be queued on the thread pool so that it executes them. But how to know when the current run() thread (within the GameBoard) can continue the calculations for the next cycle of the board? Well … it should create a CountDownLatch with the number set to the number of columns to calculate (i.e. the number of BladeRunner objects created). This overall thread will then await on this latch before continuing the next cycle. Each “BladeRunner” will then do a single countDown() on this latch at the end of its run method to indicate it has finished. Thus the thread in the GameBoard will only continue once all the columns have been calculated for the current board.Your challenge is to work out the detail required to get this architecture to work and also to worry about concurrency aspects – where might you need to add volatiles or synchronization? You should be accurate in your analysis and not just add volatiles and synchronization everywhere!*** Take a copy of your Java code with 4 threads assigned to the thread pool. Label the code: “ConwaysGameOfLife_VERSION3.java”*** QUESTION 5: Experiment with different numbers of threads used in the thread pool (for example try 1 thread, 2 threads, 4 threads, 6 threads, 8 threads, etc). Each time record three (or better five) measurements of milliseconds for 100,000 cycles of the board. Work out average / standard deviation of times and produce a table / graph to show what might be the optimal number of threads for your system.*** Please use the Moodle Forum to ask any questions about this coursework ****** Upload the three versions of your code and also your answers to Moodle ***转自:http://www.daixie0.com/contents/9/4677.html