1、wait和sleep的区别
sleep: 不释放锁对象, 释放CPU使用权
在休眠的时间内,不能唤醒
wait: 释放锁对象, 释放CPU使用权
在等待的时间内,能唤醒
2、线程的生命周期(五中状态的切换流程)
新建(new Thread)
当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。
例如:Thread t1=new Thread();
就绪(runnable)
线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源。例如:t1.start();
运行(running)
线程获得CPU资源正在执行任务(run()方法),此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。
死亡(dead)
当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。
自然终止:正常运行run()方法后终止
异常终止:调用stop()方法让一个线程终止运行
堵塞(blocked)
由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。
正在睡眠:用sleep(long t) 方法可使线程进入睡眠方式。一个睡眠着的线程在指定的时间过去可进入就绪状态。
正在等待:调用wait()方法。(调用motify()方法回到就绪状态)
被另一个线程所阻塞:调用suspend()方法。(调用resume()方法恢复)
3、有一个抽奖池,该抽奖池中存放了奖励的金额,该抽奖池用一个数组int[] arr = {10,5,20,50,100,200,500,800,2,80,300};
创建两个抽奖箱(线程)设置线程名称分别为“抽奖箱1”,“抽奖箱2”,随机从arr数组中获取奖项元素并打印在控制台上,格式如下:
抽奖箱1 又产生了一个 10 元大奖
抽奖箱2 又产生了一个 100 元大奖
//.....
1 /** 2 * 抽奖池 3 * 4 * @author vanguard 5 * 6 */ 7 public class PoolThread extends Thread { 8 //定义抽奖池数组 9 private int[] arr = { 10, 5, 20, 50, 100, 200, 500, 800, 2, 80, 300 }; 10 //定义奖金个数 11 private int num = arr.length; 12 //定义标记数组 13 private boolean[] flag = new boolean[num]; 14 public void run() { 15 while (true) { 16 synchronized (this) { 17 if(num > 0) { 18 Random r = new Random(); 19 int index = r.nextInt(arr.length); 20 //如果下标为索引的标记数组为false,代表不重复 21 if(!flag[index]) { 22 //将下标下的标记数组设为true,代表已经用过 23 flag[index] = true; 24 System.out.println(Thread.currentThread().getName() + "又产生了" 25 + arr[index] + "元大奖"); 26 //奖金个数减一 27 num--; 28 } 29 } 30 } 31 32 } 33 } 34 }
1 ** 2 * 3、有一个抽奖池,该抽奖池中存放了奖励的金额,该抽奖池用一个数组int[] arr = {10,5,20,50,100,200,500,800,2,80,300}; 3 创建两个抽奖箱(线程)设置线程名称分别为“抽奖箱1”,“抽奖箱2”,随机从arr数组中获取奖项元素并打印在控制台上,格式如下: 4 5 抽奖箱1 又产生了一个 10 元大奖 6 抽奖箱2 又产生了一个 100 元大奖 7 //..... 8 * @author vanguard 9 * 10 */ 11 public class Demo01 { 12 public static void main(String[] args) { 13 PoolThread pt = new PoolThread(); 14 Thread t0 = new Thread(pt); 15 t0.setName("抽奖箱1"); 16 Thread t1 = new Thread(pt); 17 t1.setName("抽奖箱2"); 18 19 t0.start(); 20 t1.start(); 21 } 22 }
4、某公司组织年会,会议入场时有两个入口,在入场时每位员工都能获取一张双色球彩票,假设公司有100个员工,利用多线程模拟年会入场过程,
并分别统计每个入口入场的人数,以及每个员工拿到的彩票的号码。线程运行后打印格式如下:
编号为: 2 的员工 从后门 入场! 拿到的双色球彩票号码是: [17, 24, 29, 30, 31, 32, 07]
编号为: 1 的员工 从后门 入场! 拿到的双色球彩票号码是: [06, 11, 14, 22, 29, 32, 15]
//.....
从后门入场的员工总共: 13 位员工
从前门入场的员工总共: 87 位员工
1 /** 2 * 员工进入会场,获取双色球彩票,统计每位员工的彩票号码 3 * 前门、后门员工个数 4 * @author vanguard 5 * 6 */ 7 public class Entering implements Runnable { 8 private int frontNum = 0; 9 private int backNum = 0; 10 private static int person = 100; 11 12 public void run() { 13 while(true) { 14 synchronized (this) { 15 String ThreadName = Thread.currentThread().getName(); 16 if(person < 0) { 17 return; 18 } 19 if(person > 0) { 20 if(ThreadName.equals("前门")) { 21 frontNum++; 22 System.out.print("编号为" + (100 - person + 1) + "的员工 从" + ThreadName + " 入场,拿到的双色球彩票号码是:"); 23 person--; 24 getNum(); 25 } 26 if(ThreadName.equals("后门")) { 27 backNum++; 28 System.out.print("编号为" + (100 - person + 1) + "的员工 从" + ThreadName + " 入场,拿到的双色球彩票号码是:"); 29 person--; 30 getNum(); 31 } 32 } 33 if(person == 0) { 34 System.out.println("从前门入场的员工总共: " + frontNum + "位员工"); 35 System.out.println("从后门入场的员工总共: " + backNum + "位员工"); 36 person--; 37 } 38 } 39 } 40 41 42 } 43 44 public void getNum() { 45 List<Integer> list = new ArrayList<Integer>(); 46 for(int i = 0; i < 7; i++) { 47 Random r = new Random(); 48 int num = r.nextInt(30) + 1; 49 if(list.contains(num)) { 50 num = r.nextInt(30) + 1; 51 } 52 list.add(num); 53 } 54 System.out.println(list); 55 } 56 }
/** * 4、某公司组织年会,会议入场时有两个入口,在入场时每位员工都能获取一张双色球彩票,假设公司有100个员工,利用多线程模拟年会入场过程, 并分别统计每个入口入场的人数,以及每个员工拿到的彩票的号码。线程运行后打印格式如下: 编号为: 2 的员工 从后门 入场! 拿到的双色球彩票号码是: [17, 24, 29, 30, 31, 32, 07] 编号为: 1 的员工 从后门 入场! 拿到的双色球彩票号码是: [06, 11, 14, 22, 29, 32, 15] //..... 从后门入场的员工总共: 13 位员工 从前门入场的员工总共: 87 位员工 * @author vanguard * */ public class Demo02 { public static void main(String[] args) { Entering e = new Entering(); Thread t0 = new Thread(e, "前门"); Thread t1 = new Thread(e, "后门"); t0.start(); t1.start(); } }