1. 创建两个线程,其中一个输出1-52,另外一个输出A-Z。输出格式要求:12A 34B 56C 78D
// 同步方法 synchronized修饰函数 // 思考:如何保证主线程最后的结束而非阻塞? //注意: notifyall()的位置在当前线程wait()的前面 //java print不换行 println自动换行
// 思考:如何保证主线程最后的结束而非阻塞? //注意: notifyall()的位置在当前线程wait()的前面 public class examination_16_1 { // 这个类相当于共享变量 //同步监视器类,提供线程安全的方法 class printResult{ private int number=1; private char character='A'; //提供两个synchronized方法 // synchronized方法 ;notifyall()的位置在当前线程wait()的前面 public synchronized void printnumber(){ System.out.print(number+""+(number+1)); number+=2; notifyAll(); try { // 大于52之后不再等待; if (number <= 52) wait(); //使用while(number <= 52) wait();会一直循环,后面notify也跳不出来 } catch (Exception e) { System.out.println(e.toString()); } } public synchronized void printcharacter(){ System.out.println(character+" "); character+=1; notifyAll(); try { // 大于Z之后不再等待;如果不加最后不会结束!!阻塞了 if(character<='Z') wait(); }catch (Exception e){ System.out.println(e.toString()); } } } class Number implements Runnable{ private printResult printresult; public Number(printResult p){ this.printresult=p; } private int i=0; public void run(){ for(;i<26;i++) { //调用同步监视器中的方法 printresult.printnumber(); //System.out.println(Thread.currentThread().getName()+" "+i); } } } class Character implements Runnable{ private printResult printresult; public Character(printResult p){ this.printresult=p; } public void run(){ for(int i=0;i<26;i++) { //调用同步监视器中的方法 printresult.printcharacter(); } } } public static void main(String[] args){ examination_16_1 examination=new examination_16_1(); printResult p = examination.new printResult(); Number number=examination.new Number(p); Character character = examination.new Character(p); // 启动两个线程,一个输出数字、一个输出字母 new Thread(number).start(); new Thread(character).start(); // new Thread(number,"线程0").start(); // new Thread(number,"线程1").start(); try { //希望 子线程在start就绪后立即启动,那么可以将主线程sleep 15毫秒 Thread.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } } }2.使用三个线程使得ABC 循环输出十次
// 思考:如何保证主线程最后的结束而非阻塞? public class examination_16_2 { //提供一个包含synchronized 方法的类 // while(!isA) 用while好,正确,if总是不对 private boolean isA=true; private boolean isB=false; private boolean isC=false; private int count=0; class Print{ public synchronized void printA(){ while(isA) { System.out.print("A"); isA=false; isB=true; isC=false; notifyAll(); } while(!isA){ try{ wait(); }catch (Exception e){ System.out.println(e.toString()); } } } public synchronized void printB() { while (isB) { System.out.print("B"); isA = false; isB = false; isC = true; notifyAll(); } while(!isB){ // 思考::如果没有这句判断,仍然无法将主线程结束?? // 因为最后输出最后一个C,notify所有线程,这时只有 B、C false会继续阻塞,需要解除 if(count>=10) break; try { wait(); } catch (Exception e) { System.out.println(e.toString()); } } } public synchronized void printC() { while(isC) { System.out.println("C"+" "); count++; System.out.println("count:"+count); isA = true; isC = false; isB = false; notifyAll(); } while(!isC) { if(count>=10) break; try { wait(); } catch (Exception e) { System.out.println(e.toString()); } } } } class PrintThreadA implements Runnable{ private Print p; public PrintThreadA(Print p){ this.p=p; } public void run(){ for(int i=0;i<10;i++) p.printA(); } } class PrintThreadB implements Runnable{ private Print p; public PrintThreadB(Print p){ this.p=p; } public void run(){ for(int i=0;i<10;i++) { p.printB(); } } } class PrintThreadC implements Runnable{ private Print p; public PrintThreadC(Print p){ this.p=p; } public void run(){ for(int i=0;i<10;i++) { p.printC(); //思考::为什么i最后输出不到9 ?? //因为最后一次输出C后线程被阻塞—— 加上if(count>10) beark; 才会输出 // i++ 是在循环体内部执行完毕后执行 System.out.print( "i:" + i + " "); } } } public static void main(String[] args){ examination_16_2 exm =new examination_16_2(); Print p=exm.new Print(); PrintThreadA pA = exm.new PrintThreadA(p); PrintThreadB pB =exm.new PrintThreadB(p); PrintThreadC pC =exm.new PrintThreadC(p); new Thread(pA).start(); new Thread(pB).start(); new Thread(pC).start(); } }3.有三个车库,模拟多个用户停车、离开的效果 //思考1: 生产者消费者模式? //思考2:还是用一个同步监视器类,提供线程安全的carin、carout函数;;一个入库线程、一个出库线程。
//使用阻塞队列BlockingQueue public class examination_16_3 { class CarStore{ //阻塞队列 private BlockingQueue<Integer> bq; public CarStore(BlockingQueue<Integer> bq){ this.bq=bq; } public synchronized void carin(){ for(int i=1;i<=3;i++) { try { //queue put方法尝试加入新元素,如果是满队列,会进入wait状态 if(!bq.contains(i)) { notifyAll(); bq.put(i); Thread.currentThread().sleep(500); System.out.println(Thread.currentThread().getName()+":入库"+i); } //Thread.currentThread().sleep(1000); }catch (Exception e){ System.out.println(e.toString()); } } } public synchronized void carout(){ try { Thread.currentThread().sleep(100); if(!bq.isEmpty()) System.out.println(Thread.currentThread().getName()+":退出"+bq.peek()); //queue take方法尝试取出并删除队首元素,空队列则会进入阻塞状态 notifyAll(); bq.take(); }catch (Exception e){ System.out.println(e.toString()); } } } class Carstorein extends Thread { private CarStore cs; public Carstorein(CarStore cs){ this.cs=cs;} public void run() { for (int i = 0; i < 100000; i++) { cs.carin(); } } } class Carstoreout extends Thread { private CarStore cs; public Carstoreout(CarStore cs){ this.cs=cs;} public void run() { while(true) cs.carout(); } } public static void main(String[] args){ examination_16_3 exm =new examination_16_3(); //共享变量 Blockingqueue BlockingQueue<Integer> bq=new ArrayBlockingQueue<Integer>(3); CarStore cs =exm.new CarStore(bq); exm.new Carstorein(cs).start(); exm.new Carstorein(cs).start(); exm.new Carstorein(cs).start(); exm.new Carstoreout(cs).start(); exm.new Carstoreout(cs).start(); } } concle result: Thread-0:入库1 Thread-0:入库2 Thread-0:入库3 Thread-4:退出1 Thread-3:退出2 Thread-2:入库1 Thread-2:入库2 Thread-3:退出3 Thread-3:退出1 Thread-4:退出2