-1

This is the card game where four thread (player) are available and every player try to draw a card from deck and add that draw card in it pile but In the function drawCard() when trying to remove a element it give error java.util.ConcurrentModificationException . Can anyone help to with this function

import static java.util.Collections.shuffle;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class NewGame {

     public static void main(String[] args) throws InterruptedException {



         int sizeOfDeck = 31;
            System.out.println("Enter cards in the Deck");
            ArrayList<Integer> cardNumber = new ArrayList<Integer>(sizeOfDeck);
//          for (int i = 0; i <= sizeOfDeck; i++) {
//              Scanner input = new Scanner(System.in);
//              cardNumber.add(input.nextInt());
//          }
            for(int i=1 ; i<=32;i++)
            {
                cardNumber.add(i);
            }
            System.out.println("Cards: "+ cardNumber );

            shuffle(cardNumber);
            List<Integer> Piles1 = cardNumber.subList(0, 4);
            List<Integer> Piles2 = cardNumber.subList(4, 8);
            List<Integer> Piles3 = cardNumber.subList(8, 12);
            List<Integer> Piles4 = cardNumber.subList(12, 16);

            List<Integer> player1Card = cardNumber.subList(16, 20);
            List<Integer> player2Card = cardNumber.subList(20, 24);
            List<Integer> player3Card = cardNumber.subList(24, 28);
            List<Integer> player4Card = cardNumber.subList(28, 32);

            Map<Integer, Integer> player1Map = getPlayerCards(player1Card);
            Map<Integer, Integer> player2Map = getPlayerCards(player2Card);
            Map<Integer, Integer> player3Map = getPlayerCards(player3Card);
            Map<Integer, Integer> player4Map = getPlayerCards(player4Card);


      Thread t1 = new Thread(new SequenceDisplayImpl(player1Map, Piles1, Piles2, "Player1"));
      Thread t2 = new Thread(new SequenceDisplayImpl(player2Map, Piles2, Piles3, "Player2"));
      Thread t3 = new Thread(new SequenceDisplayImpl(player3Map, Piles3, Piles4, "Player3"));
      Thread t4 = new Thread(new SequenceDisplayImpl(player4Map, Piles4, Piles1, "Player4"));
      t1.start();
      t2.start();
      t3.start();
      t4.start();

     }
     private static Map<Integer, Integer> getPlayerCards(List<Integer> playerCard) {

            Map<Integer, Integer> cardsMap = null;

            for (Integer card : playerCard) {
                if (cardsMap == null) {
                    cardsMap = new HashMap<Integer, Integer>();
                }

                Integer count = cardsMap.get(card);
                if (count == null) {
                    cardsMap.put(card, 1);
                } else {
                    cardsMap.put(card, cardsMap.get(card) + 1);
                }
            }

            return cardsMap;
         }

}

Player.java

import java.util.Collections;
import java.util.List;
import java.util.Map;

class SequenceDisplayImpl implements Runnable {
    static Object monitor = new Object();
        static boolean one = true;
        static boolean two = false;
        static boolean three = false;
        static boolean four = false;
        private Map<Integer, Integer> holdings;
        private List<Integer> deckToUseToDraw;
        private List<Integer> deckToUseForDiscard;
        private Integer currentlyDrawnCard;
        private String playerTrun;
        private boolean hasWon = false;


      public SequenceDisplayImpl(Map<Integer, Integer>holdings, List<Integer> drawDeck, List<Integer> discardDeck, String playerTurn) {

          this.holdings = holdings;
            this.deckToUseToDraw = drawDeck;
            this.deckToUseForDiscard = discardDeck;
            this.playerTrun = playerTurn;
        // TODO Auto-generated constructor stub
    }

    public void run() {
       startGame();
      }

      private void startGame() {
       try {
            while (true) {
                 Thread.sleep(1000);
                 synchronized (monitor) {
                  if ( playerTrun.equalsIgnoreCase("Player1")) 
                  {
                       if (!one) 
                       {
                        monitor.wait();
                       }
                       else {
                        //Card Draw from pile1
                        int dCard= drawCard(deckToUseToDraw);
//                       System.out.println("player 1 DrawCardPile"+deckToUseToDraw);
//                       System.out.println("Player1"+holdings);
//                       System.out.println(deckToUseForDiscard);

                        System.out.println("Player1");
                        one = false;
                        two = true;
                        three = false;
                        four = false;
                        monitor.notifyAll();
                       }
                  }
                  if ( playerTrun.equalsIgnoreCase("Player2")) 
                  {
                       if (!two)
                       {
                        monitor.wait();
                       } else 
                       {
                          int dCard1= drawCard(deckToUseToDraw);
//                        System.out.println("player 2 DrawCardPile"+deckToUseToDraw);
//                           System.out.println(holdings);
//                           System.out.println(deckToUseForDiscard);

                        System.out.println("Player2");
                        one = false;
                        two = false;
                        three = true;
                        four = false;
                        monitor.notifyAll();
                       }
                  }
                  if ( playerTrun.equalsIgnoreCase("Player3"))
                  {
                       if (!three)
                       {
                        monitor.wait();
                       } else
                       {
//                         System.out.println(deckToUseToDraw);
//                           System.out.println(holdings);
//                           System.out.println(deckToUseForDiscard);


                          // int dCard= drawCard(deckToUseToDraw);

                        System.out.println("Player3");
                        one = false;
                        two = false;
                        three = false;
                        four = true;
                        monitor.notifyAll();
                       }
                  }
                  if ( playerTrun.equalsIgnoreCase("Player4")) 
                  {
                       if (!four)
                       {
                        monitor.wait();
                       } 
                       else {
                           //int dCard= drawCard(deckToUseToDraw);
                             // System.out.println(deckToUseToDraw);

                        System.out.println("Player4");
                        one = true;
                        two = false;
                        three = false;
                        four = true;
                        monitor.notifyAll();
                       }
                   }
             }
        }
       } catch (InterruptedException e) {
        e.printStackTrace();
       }

      }





    public  int  drawCard(List<Integer> deckToUseToDraw) throws InterruptedException {
        // TODO Auto-generated method stub

        System.out.println(deckToUseToDraw);
        int dCard=deckToUseToDraw.remove(0);

        return dCard;


    }

     }
sankey
  • 37
  • 1
  • 7
  • Please read "How to create a [mcve]". Then use the [edit] link to improve your question (do not add more information via comments). Otherwise we are not able to answer your question and help you. A) dont give us code that is full with commented-out code. Instead, ideally, give us code that we can actually run to repro your problem. B) then give the full stack trace from that exception. What matters here is the path that leads to the exception. – GhostCat Sep 18 '19 at 03:40
  • And having said that: this exception is really clear, and well documented: https://stackoverflow.com/questions/223918/iterating-through-a-collection-avoiding-concurrentmodificationexception-when-re – GhostCat Sep 18 '19 at 03:41
  • Possible duplicate of [Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loop](https://stackoverflow.com/questions/223918/iterating-through-a-collection-avoiding-concurrentmodificationexception-when-re) – Stefan Becker Sep 18 '19 at 05:18

1 Answers1

0

First, code to interfaces, not their implementations:

List<Integer> l = new ArrayList<>();

Second, the ArrayList<T> is not thread-safe. Looping through an ArrayList<> is a compound action: check-then-act. It needs to be atomic. If some other thread modifies this list in b/w, you'll see a ConcurrentModificationException. The reason is that it is fail-fast. That is, it'll not wait to tell you that the list was modified while a thread was iterating through it.

I suggest you read on thread-safe collections in Java.

Prashant Pandey
  • 4,332
  • 3
  • 26
  • 44