活动介绍

下面多线程售票tickets为什么报“Cannot resolve symbol 'tickets'”public synchronized void sale() { if(tickets.getNum() > 0) { try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } if(tickets.getNum() > 0) { int num = tickets.getNum(); System.out.println(Thread.currentThread().getName() + " 正在售卖第 " + num + " 张票,剩余:" + (--num)); tickets.setNum(num); } } } }

时间: 2024-02-14 11:19:43 浏览: 188
根据你提供的代码,很可能是因为没有定义变量 tickets。请确认你在代码中是否定义了 tickets 变量,且其类型为一个包含getNum() 和setNum() 方法的类。如果没有定义,可以先定义一个 Ticket 类,并在定义的类中创建一个 Ticket 对象 tickets,作为售票的实例变量。
相关问题

多线程买票下面的代码为什么会tickets会报错public synchronized void sale() { if(tickets.getNum() > 0) { try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } if(tickets.getNum() > 0) { int num = tickets.getNum(); System.out.println(Thread.currentThread().getName() + " 正在售卖第 " + num + " 张票,剩余:" + (--num)); tickets.setNum(num); } } }

根据你提供的代码,我们无法确定报错的具体原因。但是,从该代码片段来看,tickets可能因为以下原因报错: 1. tickets对象未初始化:如果在Operate对象的构造函数中没有正确初始化tickets对象,则会导致在sale方法中调用tickets对象的getNum和setNum方法时出现NullPointerException。 2. tickets对象为null:如果在Operate对象的构造函数中没有正确传入tickets对象,则会导致在sale方法中调用tickets对象的getNum和setNum方法时出现NullPointerException。 3. tickets对象在其他线程中已被修改:如果其他线程对tickets对象进行了修改,而没有使用锁来保证同步,则会导致在sale方法中调用tickets对象的getNum和setNum方法时出现线程安全问题。 为了确定具体的原因,需要进一步查看代码,并分析报错信息。

找出问题所在改进多线程买票public class Operate implements Runnable{ int num; public Operate(Tickets tickets) { this.num = tickets.getNum(); } @Override public void run() { sale(); } public synchronized void sale() { if(tickets.getNum() > 0) { try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } if(tickets.getNum() > 0) { int num = tickets.getNum(); System.out.println(Thread.currentThread().getName() + " 正在售卖第 " + num + " 张票,剩余:" + (--num)); tickets.setNum(num); } } } }

这段代码存在两个问题: 1. 多线程共享了同一个 Tickets 对象,但是在 Operate 构造函数中获取的 num 只是一个拷贝,而不是引用,所以多个线程间并不共享 num。这会导致多个线程尝试售卖同一张票,从而导致错误。 2. synchronized 锁住的是 sale() 方法,而不是操作共享资源的代码块。这意味着多个线程可以进入 sale() 方法,但是只有一个线程会执行操作共享资源的代码块,从而降低了代码的并发性。 改进方法如下: 1. 在 Operate 中增加一个 Tickets 成员变量,并且在构造函数中将其赋值为传入的 tickets 对象。 2. 将 sale() 方法中的 synchronized 去掉,并且将操作共享资源的代码块用 synchronized 包裹起来。 改进后的代码如下: ``` public class Operate implements Runnable { private Tickets tickets; public Operate(Tickets tickets) { this.tickets = tickets; } @Override public void run() { sale(); } public void sale() { synchronized (tickets) { if (tickets.getNum() > 0) { try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } if (tickets.getNum() > 0) { int num = tickets.getNum(); System.out.println(Thread.currentThread().getName() + " 正在售卖第 " + num + " 张票,剩余:" + (--num)); tickets.setNum(num); } } } } } ```
阅读全文

相关推荐

package cinemasystem; import java.io.*; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; // 用户基类 abstract class User implements Serializable { private String username; private String password; private String type; public User(String username, String password, String type) { this.username = username; this.password = password; this.type = type; } public abstract void showMenu(); // Getters public String getUsername() { return username; } public String getPassword() { return password; } public String getType() { return type; } public void setPassword(String password) { this.password = password; } public boolean validate(String inputUsername, String inputPassword) { return this.username.equals(inputUsername) && this.password.equals(inputPassword); } } // 管理员类 class Admin extends User { public Admin(String username, String password) { super(username, password, "Admin"); } @Override public void showMenu() { AdminManager.showMenu(this); } } // 前台类 class TicketSeller extends User { public TicketSeller(String username, String password) { super(username, password, "TicketSeller"); } @Override public void showMenu() { TicketSellerManager.showMenu(this); } } // 影片类 class Movie implements Serializable { private String title; private int duration; // 分钟 public Movie(String title, int duration) { this.title = title; this.duration = duration; } // Getters public String getTitle() { return title; } public int getDuration() { return duration; } } // 场次类 class Session implements Serializable { private String id; private Movie movie; private LocalDateTime startTime; private double price; private boolean[][] seats; public Session(String id, Movie movie, LocalDateTime startTime, double price, int rows, int cols) { this.id = id; this.movie = movie; this.startTime = startTime; this.price = price; this.seats = new boolean[rows][cols]; for (boolean[] row : seats) { Arrays.fill(row, true); } } // Getters public String getId() { return id; } public Movie getMovie() { return movie; } public LocalDateTime getStartTime() { return startTime; } public double getPrice() { return price; } public boolean[][] getSeats() { return seats; } public boolean bookSeat(int row, int col) { if (row < 0 || row >= seats.length || col < 0 || col >= seats[0].length) return false; if (seats[row][col]) { seats[row][col] = false; return true; } return false; } public void showSeats() { System.out.println("\n 座位分布:"); for (int i = 0; i < seats.length; i++) { System.out.print((i + 1) + "排: "); for (int j = 0; j < seats[i].length; j++) { System.out.print(seats[i][j] ? "[ ] " : "[X] "); } System.out.println(); } } } // 票类 class Ticket implements Serializable { private String id; private Session session; private int row; private int col; private LocalDateTime time; public Ticket(String id, Session session, int row, int col) { this.id = id; this.session = session; this.row = row; this.col = col; this.time = LocalDateTime.now(); } public String getInfo() { return String.format("票号: %s\n影片: %s\n时间: %s\n座位: %d排%d座\n价格: %.2f元", id, session.getMovie().getTitle(), session.getStartTime().format(DateTimeFormatter.ofPattern("MM - dd HH:mm")), row + 1, col + 1, session.getPrice()); } // 新增获取场次方法,解决找不到符号问题 public Session getSession() { return session; } // 新增获取排数方法,解决getRow()找不到符号问题 public int getRow() { return row; } // 新增获取列数方法,考虑可能后续有获取col的需求 public int getCol() { return col; } } // 文件管理类 class FileManager { private static final String USERS_FILE = "users.dat"; private static final String MOVIES_FILE = "movies.dat"; private static final String SESSIONS_FILE = "sessions.dat"; private static final String TICKETS_FILE = "tickets.dat"; // 保存对象到文件 public static void save(Object obj, String filename) { try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filename))) { oos.writeObject(obj); } catch (IOException e) { System.out.println("保存失败: " + e.getMessage()); } } // 从文件加载对象 public static Object load(String filename) { try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename))) { return ois.readObject(); } catch (Exception e) { return null; } } // 用户管理 public static void saveUsers(List<User> users) { save(users, USERS_FILE); } @SuppressWarnings("unchecked") public static List<User> loadUsers() { Object data = load(USERS_FILE); if (data == null) { List<User> defaultUsers = new ArrayList<>(); defaultUsers.add(new Admin("admin", "admin123")); defaultUsers.add(new TicketSeller("seller", "seller123")); return defaultUsers; } return (List<User>) data; } // 电影管理 public static void saveMovies(List<Movie> movies) { save(movies, MOVIES_FILE); } @SuppressWarnings("unchecked") public static List<Movie> loadMovies() { Object data = load(MOVIES_FILE); return data != null ? (List<Movie>) data : new ArrayList<>(); } // 场次管理 public static void saveSessions(List<Session> sessions) { save(sessions, SESSIONS_FILE); } @SuppressWarnings("unchecked") public static List<Session> loadSessions() { Object data = load(SESSIONS_FILE); return data != null ? (List<Session>) data : new ArrayList<>(); } // 票务管理 public static void saveTickets(List<Ticket> tickets) { save(tickets, TICKETS_FILE); } @SuppressWarnings("unchecked") public static List<Ticket> loadTickets() { Object data = load(TICKETS_FILE); return data != null ? (List<Ticket>) data : new ArrayList<>(); } } // 管理员功能 class AdminManager { private static final Scanner scanner = new Scanner(System.in); private static int sessionIdCounter = 1; public static void showMenu(Admin admin) { while (true) { System.out.println("\n=== 管理员菜单 ==="); System.out.println("1. 添加影片"); System.out.println("2. 添加场次"); System.out.println("3. 查看场次"); System.out.println("4. 修改密码"); System.out.println("0. 退出"); System.out.print("请选择: "); int e = scanner.nextInt(); scanner.nextLine(); switch (e) { case 1: addMovie(); break; case 2: addSession(); break; case 3: viewSessions(); break; case 4: changePassword(admin); break; case 0: return; default: System.out.println("无效选择"); } } } private static void addMovie() { System.out.print("输入影片名称: "); String title = scanner.nextLine(); System.out.print("输入时长(分钟): "); int duration = scanner.nextInt(); scanner.nextLine(); List<Movie> movies = FileManager.loadMovies(); movies.add(new Movie(title, duration)); FileManager.saveMovies(movies); System.out.println("影片添加成功!"); } private static void addSession() { List<Movie> movies = FileManager.loadMovies(); if (movies.isEmpty()) { System.out.println("请先添加影片!"); return; } System.out.println("可选影片:"); for (int i = 0; i < movies.size(); i++) { System.out.printf("%d. %s (%d分钟)\n", i + 1, movies.get(i).getTitle(), movies.get(i).getDuration()); } System.out.print("选择影片编号: "); int movieIndex = scanner.nextInt() - 1; scanner.nextLine(); if (movieIndex < 0 || movieIndex >= movies.size()) { System.out.println("无效选择!"); return; } System.out.print("输入开始时间(yyyy - MM - dd HH:mm): "); String timeStr = scanner.nextLine(); LocalDateTime time; try { time = LocalDateTime.parse(timeStr, DateTimeFormatter.ofPattern("yyyy - MM - dd HH:mm")); } catch (Exception e) { System.out.println("时间格式错误!"); return; } System.out.print("输入票价: "); double price = scanner.nextDouble(); scanner.nextLine(); System.out.print("输入座位排数: "); int rows = scanner.nextInt(); System.out.print("输入每排座位数: "); int cols = scanner.nextInt(); scanner.nextLine(); String sessionId = "S" + sessionIdCounter++; Session session = new Session(sessionId, movies.get(movieIndex), time, price, rows, cols); List<Session> sessions = FileManager.loadSessions(); sessions.add(session); FileManager.saveSessions(sessions); System.out.println("场次添加成功! ID: " + sessionId); } private static void viewSessions() { List<Session> sessions = FileManager.loadSessions(); if (sessions.isEmpty()) { System.out.println("暂无场次"); return; } for (Session s : sessions) { System.out.printf("ID: %s, 影片: %s, 时间: %s, 价格: %.2f\n", s.getId(), s.getMovie().getTitle(), s.getStartTime().format(DateTimeFormatter.ofPattern("MM - dd HH:mm")), s.getPrice()); } } // 将方法访问修饰符改为public,解决private访问控制问题 public static void changePassword(User user) { System.out.print("输入新密码: "); String newPassword = scanner.nextLine(); user.setPassword(newPassword); // 更新所有用户 List<User> users = FileManager.loadUsers(); for (User u : users) { if (u.getUsername().equals(user.getUsername())) { u.setPassword(newPassword); } } FileManager.saveUsers(users); System.out.println("密码修改成功!"); } } // 前台售票功能 class TicketSellerManager { private static final Scanner scanner = new Scanner(System.in); private static int ticketIdCounter = 1; public static void showMenu(TicketSeller seller) { while (true) { System.out.println("\n=== 前台菜单 ==="); System.out.println("1. 售票"); System.out.println("2. 退票"); System.out.println("3. 修改密码"); System.out.println("0. 退出"); System.out.print("请选择: "); int choice = scanner.nextInt(); scanner.nextLine(); switch (choice) { case 1: sellTicket(); break; case 2: refundTicket(); break; case 3: changePassword(seller); break; case 0: return; default: System.out.println("无效时选择"); } } } private static void sellTicket() { List<Session> sessions = FileManager.loadSessions(); if (sessions.isEmpty()) { System.out.println("暂无场次"); return; } System.out.println("当前的场次:"); for (int i = 0; i < sessions.size(); i++) { Session s = sessions.get(i); System.out.printf("%d. %s %s ¥%.2f\n", i + 1, s.getMovie().getTitle(), s.getStartTime().format(DateTimeFormatter.ofPattern("MM - dd HH:mm")), s.getPrice()); } System.out.print("选择场次: "); int sessionIdx = scanner.nextInt() - 1; scanner.nextLine(); if (sessionIdx < 0 || sessionIdx >= sessions.size()) { System.out.println("无效选择!"); return; } Session session = sessions.get(sessionIdx); session.showSeats(); System.out.print("选择排数: "); int row = scanner.nextInt() - 1; System.out.print("选择座位号: "); int k = scanner.nextInt() - 1; scanner.nextLine(); if (!session.bookSeat(row, k)) { System.out.println("座位不可用!"); return; } String ticketId = "T" + ticketIdCounter++; Ticket ticket = new Ticket(ticketId, session, row, k); List<Ticket> tickets = FileManager.loadTickets(); tickets.add(ticket); FileManager.saveTickets(tickets); FileManager.saveSessions(sessions); System.out.println("\n售票成功!"); System.out.println(ticket.getInfo()); } private static void refundTicket() { List<Ticket> tickets = FileManager.loadTickets(); if (tickets.isEmpty()) { System.out.println("暂无票务记录"); return; } System.out.print("输入票号: "); String ticketId = scanner.nextLine(); Ticket target = null; for (Ticket t:tickets) { if (t.getInfo().contains(ticketId)) { target = t; break; } } if (target == null) { System.out.println("票号不存在!"); return; } // 取消座位 List<Session> sessions = FileManager.loadSessions(); for (Session s:sessions) { if (s.getId().equals(target.getSession().getId())) { int row = target.getRow(); int col = target.getCol(); if (row >= 0 && row < s.getSeats().length && col >= 0 && col < s.getSeats()[0].length) { s.getSeats()[row][col] = true; // 标记座位可用 } break; } } // 移除票 tickets.remove(target); FileManager.saveTickets(tickets); FileManager.saveSessions(sessions); System.out.println("退票成功!"); } private static void changePassword(User user) { AdminManager.changePassword(user); } } // 主程序 public class test2 { private static final Scanner scanner = new Scanner(System.in); public static void main(String[] args) { List<User> users = FileManager.loadUsers(); while (true) { System.out.println("\n=== 电影院管理系统 ==="); System.out.print("用户名: "); String username = scanner.nextLine(); System.out.print("密码: "); String password = scanner.nextLine(); User currentUser = null; for (User user : users) { if (user.validate(username, password)) { currentUser = user; break; } } if (currentUser != null) { System.out.println("登录成功! 角色: " + currentUser.getType()); currentUser.showMenu(); } else { System.out.println("用户名或密码错误!"); } } } }这段代码的uml图,用plantuml语言输出