1.阻塞 2.就绪 3.阻塞 4.Runnable 5.join() 6.synchronized 7.notify()和notifyAll() 8.Object
1.A 2.D 3.C 4.C 5.C 6.B 7.AD 8.A 9.C 10.D
1.
继承Thread()方法
优点:可以直接调用Thread类里的方法,代码简单
缺点:如果已经有了父类就不能使用这种方法。
实现Runnable接口
优点:即使自己定义的线程类有了父类也可以实现接口,而且接口是可以多实现的
缺点:不能直接使用Thread类的方法,必须获得线程对象后才能使用Thread的方法,代码复杂
2.
-
sleep()方法必须传入参数,参数就是时间,时间到了就会自动醒来。
Wait()方法可以传入也可以不传参数,传入参数就是在参数结束的时间后等待,不传参数就是直接等待。
-
sleep方法在同步方法或同步代码块中不释放锁(拥有CPU的执行权,因为可以自动醒来)
wait()方法在同步方法或同步代码块中释放锁(等待时没有CPU执行权,否则其他线程无法获取执行权
3.
1.用synchronized修饰的同步方法或者同步代码块中使用Object类提供的wait()、notify()、notifyAll()方法实现线程通信
wait(): 在其他线程调用此对象的notify()方法或notifyAll()方法前,导致当前线程等待。
notify():唤醒在此对象监视器上等待的单个线程。
notifyAll():唤醒在此对象监视器上等待的所有线程。
2.使用ReentrantLock类的lock()和unlock()方法进行同步
lock():获取锁。
unlock():试图释放此锁
3.使用阻塞队列控制通信
put(E e):尝试把E元素放入BlockingQueue中,如果该队列的元素已满,则阻塞该线程。
take():尝试从BlockingQueue的头部取出元素,如果该队列的元素已空,则阻塞该线程。
package com.zuikc.kehoutest;import java.security.GeneralSecurityException; public class Test3 { /* * 需求:铁路售票,一共100张,通过四个窗口卖完. */ public static void main(String[] args) { new Ticket2().start(); new Ticket2().start(); new Ticket2().start(); new Ticket2().start(); new Ticket2().start(); } } class Ticket2 extends Thread{ private static int ticket = 100; public void run() { while(true) { synchronized(Ticket2.class) { if (ticket <= 0) { break; } try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(getName() + "您购买的票号是" + ticket--); } } } }
package com.zuikc.kehoutest; public class Test9 { /* * 需求: * 2. 编写两个线程,一个线程打印1-52的整数,另一个线程打印字母A-Z。打印顺序为12A34B56C….5152Z。即按照整数和字母的顺序从小到大打印,并且每打印两个整数后,打印一个字母,交替循环打印,直到打印到整数52和字母Z结束。 要求: 1) 编写打印类Printer,声明私有属性index,初始值为1,用来表示是第几次打印。 2) 在打印类Printer中编写打印数字的方法print(int i),3的倍数就使用wait()方法等待,否则就输出i,使用notifyAll()进行唤醒其它线程。 3) 在打印类Printer中编写打印字母的方法print(char c),不是3的倍数就等待,否则就打印输出字母c,使用notifyAll()进行唤醒其它线程。 4) 编写打印数字的线程NumberPrinter继承Thread类,声明私有属性private Printer p;在构造方法中进行赋值,实现父类的run方法,调用Printer类中的输出数字的方法。 5) 编写打印字母的线程LetterPrinter继承Thread类,声明私有属性private Printer p;在构造方法中进行赋值,实现父类的run方法,调用Printer类中的输出字母的方法。 6) 编写测试类Test,创建打印类对象,创建两个线程类对象,启动线程。 */ public static void main(String[] args) { Printer3 p = new Printer3(); Thread t1 = new NumberPrinter(p); Thread t2 = new LetterPrinter(p); t1.start(); t2.start(); } } class Printer3 { private int index = 1; public void print1(int i) throws InterruptedException { synchronized(this) { while(index % 3 == 0) { this.wait(); } System.out.println(i); index++; this.notifyAll(); } } public void print2(char c) throws InterruptedException { synchronized(this) { while(index % 3 != 0) { this.wait(); } System.out.println(c); index++; this.notifyAll(); } } } class NumberPrinter extends Thread { private Printer3 p; public NumberPrinter(Printer3 p) { this.p = p; } public void run() { int i = 1; while(i <= 52) { try { p.print1(i); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } i++; } } } class LetterPrinter extends Thread { private Printer3 p; public LetterPrinter(Printer3 p) { this.p = p; } public void run() { char c = 'A'; while(c <= 'Z') { try { p.print2(c); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } c++; } } }
package com.zuikc.kehoutest; public class Test10 { /* * 设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1。 要求:使用内部类实现线程,对j增减的时候不考虑顺序问题。 */ public static void main(String[] args) { Method m = new Method(); new Thread("t1") { public void run() { while(true) { System.out.print(getName() + "..."); m.add(); } } }.start(); new Thread("t2") { public void run() { while(true) { System.out.print(getName() + "..."); m.add(); } } }.start(); new Thread("t3") { public void run() { while(true) { System.out.print(getName() + "..."); m.subtract(); } } }.start(); new Thread("t4") { public void run() { while(true) { System.out.print(getName() + "..."); m.subtract(); } } }.start(); } } class Method { private static int j; public void add() { synchronized(this) { j++; System.out.println(j); } } public void subtract() { synchronized(this) { j--; System.out.println(j); } } }
package com.zuikc.kehoutest; public class Test11 { /* * 需求:编写多线程程序,模拟多个人通过一个山洞的模拟。这个山洞每次只能通过一个人,每个人通过山洞的时间为5秒,有10个人同时准备过此山洞,显示每次通过山洞人的姓名和顺序。 */ public static void main(String[] args) { Cave c = new Cave(); Thread t1 = new Thread(c, "t1"); Thread t2 = new Thread(c, "t2"); Thread t3 = new Thread(c, "t3"); Thread t4 = new Thread(c, "t4"); Thread t5 = new Thread(c, "t5"); Thread t6 = new Thread(c, "t6"); Thread t7 = new Thread(c, "t7"); Thread t8 = new Thread(c, "t8"); Thread t9 = new Thread(c, "t9"); Thread t10 = new Thread(c, "t10"); t1.start(); t2.start(); t3.start(); t4.start(); t5.start(); t6.start(); t7.start(); t8.start(); t9.start(); t10.start(); } } class Cave implements Runnable { int count = 0; @Override public synchronized void run() { try { Thread.sleep(5000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } count++; System.out.println(Thread.currentThread().getName() + "是第" + count + "个通过山洞的"); } }