NoSuchMethodError

疯狂java第16章课后习题第一题:用java写两个线程,一个线程打印1-52,另一个线程打印字母A-Z,打印顺序为12A34B。。。5152Z。

于是在Eclipse中根据第一个java文件自己敲出的第二个java文件,二者几乎没有什么区别,可是第一个文件运行成功并正确显示结果,第二个文件运行报错:NoSuchMethodError

1.PrinterCheck.java

  1 import java.util.concurrent.locks.*;
  2 class Printer
  3 {
  4     private final Lock lock = new ReentrantLock();
  5     private final Condition cond = lock.newCondition();
  6     private final int[] arrNumber = new int[52];
  7     private int n;//arrNumber计数
  8     private final char[] arrChar = new char[26];
  9     private int c;//arrChar计数
 10     private int counter;//连续打印数字的间隔
 11     //Printer构造器
 12     public Printer( )
 13     {
 14         for(int i=0;i<arrNumber.length;i++)
 15         {
 16             arrNumber[i] = (i+1);
 17         }
 18         for(char i='A';i<'Z'+1;i++)
 19             
 20             
 21         {
 22             arrChar[i-65] = i;
 23         }
 24     }
 25     public void printNumber()
 26     {
 27         lock.lock();
 28         try
 29         {
 30             if(counter>1)
 31             {
 32                 cond.await();
 33             }
 34             else
 35             {    if(n>51) return;
 36                 System.out.print(arrNumber[n]+" ");
 37                                 n++;
 38                 counter++;
 39                 cond.signalAll();
 40             }
 41          
 42         }
 43         catch (InterruptedException e)
 44         {
 45             e.printStackTrace();
 46         }
 47         finally
 48         {
 49             lock.unlock();
 50         }
 51     }
 52     public void printChar()
 53     {
 54         lock.lock();
 55         try
 56         {
 57             if(counter<2)
 58             {
 59                 cond.await();
 60             }
 61             else
 62             {
 63                 if(c>25) return;
 64                 System.out.print(arrChar[c]+" ");
 65                 c++;
 66                 counter=0;
 67                 cond.signalAll();
 68             }
 69         }
 70         catch (InterruptedException e)
 71         {
 72             e.printStackTrace();
 73         }
 74         finally
 75         {
 76             lock.unlock();
 77         }
 78     }
 79 }
 80 class PrintNumber extends Thread
 81 {
 82     private Printer print;
 83     public PrintNumber(String name,Printer print)
 84     {
 85         super(name);
 86         this.print = print;
 87     }
 88     public void run()
 89     {
 90         for(int i=0;i<100;i++)
 91         {
 92             print.printNumber();
 93         }
 94     }
 95 }
 96 class PrintChar extends Thread
 97 {
 98     private Printer print;
 99     public PrintChar(String name,Printer print)
100     {
101         super(name);
102         this.print = print;
103     }
104     public void run()
105     {
106         for(int i=0;i<100;i++)
107         {
108              print.printChar();
109         }
110     }
111 }
112 public class PrinterCheck
113 {
114     public static void main(String[] args) throws Exception  
115     {
116         Printer print = new Printer();
117         new PrintNumber("打印数字",print).start();
118         new PrintChar("打印字符",print).start();
119     }
120 }


点击运行,结果如下:

2.MulThreadPrint.java 

    

  1 import java.util.concurrent.locks.* ;
 2 class Printer
3
{ //显示定义Lock对象 4 private final Lock lock = new ReentrantLock(); 5 //获得指定Lock对象对应的condition 6 private final Condition cond = lock.newCondition(); 7 //private final int[] arrNumber = new int[52];//保存数字的数组 8 private final int[] arrNumber = new int[52]; 9 private int nNumber;//数字的计数 10 //private final char[] arrChar = new char[26];//保存字符的数组 11 private final char[] arrChar = new char[26]; 12 private int nChar;//字符的计数 13 14 private int nInternal;//数字连续打印的间隔 15 //重写构造器对数组进行初始化赋值 16 public Printer() 17 { 18 for(int i=0;i<arrNumber.length;i++) 19 { 20 arrNumber[i] = i+1; 21 } 22 for(char i='A';i<'Z'+1;i++) 23 { 24 arrChar[i-65] = i; 25 } 26 } 27 //打印数字的方法 28 public void PrintNumber() 29 { //加锁 30 lock.lock(); 31 try 32 { //如果数字连续打印了2个,就暂停等待 33 if(nInternal>1) 34 { 35 cond.await(); 36 } 37 //如果数字连续打印少于2个,就继续打印,打印完数字之后就唤醒其他线程 38 else 39 {
//判断到最后数字时返回退出程序
40 if(nNumber==52) 41 return; 42 System.out.print(arrNumber[nNumber]+" "); 43 nNumber++; 44 nInternal++; 45 cond.signalAll(); 46 47 } 48 } 49 catch (InterruptedException ex) 50 { 51 ex.printStackTrace(); 52 } 53 //用finally块来释放锁 54 finally 55 { 56 lock.unlock(); 57 } 58 } 59 //打印字符的方法 60 public void PrintChar() 61 { 62 lock.lock(); 63 try 64 { 65 if(nInternal<2) 66 { 67 cond.await(); 68 } 69 else 70 {
//判断到最后字符时返回退出程序
71 if(nChar==26) 72 return; 73 System.out.print(arrChar[nChar]+" "); 74 nChar++; 75 nInternal = 0; 76 cond.signalAll(); 77 } 78 } 79 catch (InterruptedException ex) 80 { 81 ex.printStackTrace(); 82 } 83 //用finally块来释放锁 84 finally 85 { 86 lock.unlock(); 87 } 88 } 89 } 90 91 class PrintNumberThread extends Thread 92 { 93 private Printer Printer; 94 public PrintNumberThread(String name,Printer Printer) 95 { 96 super(name); 97 this.Printer = Printer; 98 } 99 public void run() 100 { //这里必须有for循环,不然只打印一轮 101 for(int i=0;i<100;i++) 102 { 103 Printer.PrintNumber(); 104 } 105 } 106 } 107 108 class PrintCharThread extends Thread 109 { 110 private Printer Printer; 111 public PrintCharThread(String name,Printer Printer) 112 { 113 super(name); 114 this.Printer = Printer; 115 } 116 public void run() 117 { 118 for(int i=0;i<100;i++) 119 { 120 Printer.PrintChar(); 121 } 122 } 123 } 124 125 public class MulThreadPrint 126 { 127 public static void main(String[] args) throws Exception 128 { 129 Printer Printer = new Printer(); 130 new PrintNumberThread("打印数字",Printer).start(); 131 new PrintCharThread("打印字符",Printer).start(); 132 } 133 }

点击运行,结果如下:

根据报错,是PrintNumberThread.run函数出错了,而run函数调用的是PrintNumber()函数。但实际上PrintNumber()函数是存在的。

问题原因:因为两个文件在同一个包下,而且两个文件的Printer类重名了,于是得到两个矛盾的Printer.class。将第二个文件的Printer类改个名字,再运行即可得到正确结果。

这里提供该题的第二种方法,同时也是最优方法:将ncouner去掉,直接以i%2==0来判断连续打印2个数字。

 1 class Printer2
 2 {  
 3      private final int[] arrNumber = new int[52];//保存数字的数组
 4      private final char[] arrChar = new char[26];//保存字符的数组
 5 
 6      //重写构造器对数组进行初始化赋值
 7      public Printer2()
 8      {
 9          for(int i=0;i<arrNumber.length;i++)
10          {
11              arrNumber[i] = i+1;
12          }
13          for(char i=0;i<arrChar.length;i++)
14          {
15              arrChar[i] = (char)('A'+i);
16          }
17      }
18     //定义一个打印数字的同步方法
19     public synchronized void PrintNumber()
20     {
21          for (int i = 1; i < arrNumber.length+1; i++) 
22          {     //一开始就打印数字
23                 System.out.print(arrNumber[i-1]+" "); 
24                 try
25                 {   //每连续打印两个数字后,数字线程就唤醒其他线程并且自己暂停等待
26                     if(i%2 == 0)
27                     {   
28                         notifyAll();
29                         wait();
30                     }
31                     
32                 }
33                 catch(Exception e)
34                 {
35                     e.printStackTrace(); 
36                 }                                
37         }
38     }
39     
40     public synchronized void PrintChar()
41     {
42          for(int i=0;i<arrChar.length;i++)
43          {   //一开始就打印字符
44              System.out.print(arrChar[i]+" ");
45              try
46              {    //每打印一个字符之后,字符线程就唤醒其他线程并且自己暂停等待        
47                   notifyAll();
48                   wait();              
49              }
50              catch(Exception e)
51              {
52                   e.printStackTrace(); 
53              }
54          }
55     }
56 }
57 //打印1-52
58 class PrintThreadNumber extends Thread
59 {
60     private Printer2 Printer;
61     public PrintThreadNumber(Printer2 Printer)
62     {
63         this.Printer = Printer;
64     }
65     public void run()
66     {
67         Printer.PrintNumber();
68     }
69 }
70 //打印A-Z
71 class PrintThreadChar extends Thread
72 {
73     private Printer2 Printer;
74     public PrintThreadChar(Printer2 Printer)
75     {
76         this.Printer = Printer;
77     }
78     public void run()
79     {
80         Printer.PrintChar();     
81     }
82 } 
83 
84 
85 public class MulThreadCom2
86 {
87     public static void main(String[] args) throws Exception 
88     {
89         Printer2 Printer = new Printer2(); 
90         // 启动两个线程 
91         PrintThreadNumber t1 = new PrintThreadNumber(Printer); 
92         PrintThreadChar t2 = new PrintThreadChar(Printer); 
93         t1.start(); 
94         t2.start(); 
95           
96      }
97 }
原文地址:https://www.cnblogs.com/TTTTT/p/5823718.html