今天写一个多线程同步代码快的程序时,出现意料之外的执行结果,代码如下:
package com.drz.xianchengmaipiao; /** * 1.写一个卖票的程序。 ① * 写一个类,该类实现了Runnable接口。有一个私有类型的int型的参数:tickets。票的总数,为100,完成run方法,输出结果的格式如下: * 当前窗口为:窗口a ,剩余的票数为:19,其中窗口a为线程的名称。 ② 开启四个卖票窗口(起四个线程),同时执行卖票的程序。 ③ * * @author drz * */ public class MaiPiao implements Runnable { private static int tickets; private String wins; public MaiPiao(String wins) { this.wins = wins; } private synchronized void sellTic() { if (tickets > 0) { try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } tickets--; System.out.println("窗口" + wins + ",剩余票数为:" + tickets); } } public MaiPiao() { // TODO Auto-generated constructor stub } /** * @param args */ public static void main(String[] args) { MaiPiao.tickets = 100; for (int i = 1; i <= 4; i++) { new Thread(new MaiPiao(i + "")).start(); } } @Override public void run() { while (tickets > 0) sellTic(); } public String getWins() { return wins; } public void setWins(String wins) { this.wins = wins; } }执行结果如下:省略了前面的结果输出,只保留了最后几行
窗口3,剩余票数为:8 窗口1,剩余票数为:7 窗口2,剩余票数为:5 窗口4,剩余票数为:5 窗口3,剩余票数为:4 窗口2,剩余票数为:1 窗口1,剩余票数为:1 窗口4,剩余票数为:1 窗口3,剩余票数为:0 窗口1,剩余票数为:-3 窗口2,剩余票数为:-3 窗口4,剩余票数为:-3
所以进行改进:
synchronized不加在方法上了,对方法里面的全部代码加到同步代码快中,且使用类名.class作为同步锁。
注:run方法中while循环判断是不能写进同步代码快的,否则就等同一个单线程的程序了。
package com.drz.xianchengmaipiao; /** * 1.写一个卖票的程序。 ① * 写一个类,该类实现了Runnable接口。有一个私有类型的int型的参数:tickets。票的总数,为100,完成run方法,输出结果的格式如下: * 当前窗口为:窗口a ,剩余的票数为:19,其中窗口a为线程的名称。 ② 开启四个卖票窗口(起四个线程),同时执行卖票的程序。 ③ * * @author drzwin32 * */ public class MaiPiao implements Runnable { private static int tickets; private String wins; public MaiPiao(String wins) { this.wins = wins; } private void sellTic() { synchronized(MaiPiao.class){ if (tickets > 0) { try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } tickets--; System.out.println("窗口" + wins + ",剩余票数为:" + tickets); } } } public MaiPiao() { // TODO Auto-generated constructor stub } /** * @param args */ public static void main(String[] args) { MaiPiao.tickets = 100; for (int i = 1; i <= 4; i++) { new Thread(new MaiPiao(i + "")).start(); } } @Override public void run() { while (tickets > 0) sellTic(); } public String getWins() { return wins; } public void setWins(String wins) { this.wins = wins; } }执行结果如下:
窗口2,剩余票数为:18 窗口3,剩余票数为:17 窗口3,剩余票数为:16 窗口3,剩余票数为:15 窗口3,剩余票数为:14 窗口3,剩余票数为:13 窗口3,剩余票数为:12 窗口3,剩余票数为:11 窗口3,剩余票数为:10 窗口3,剩余票数为:9 窗口3,剩余票数为:8 窗口3,剩余票数为:7 窗口3,剩余票数为:6 窗口4,剩余票数为:5 窗口1,剩余票数为:4 窗口1,剩余票数为:3 窗口1,剩余票数为:2 窗口4,剩余票数为:1 窗口4,剩余票数为:0