package com.qiku.day24; import static java.text.DateFormat.FULL; public class Test { /* 模拟生产者 和消费着 模型 两个线程 : 生产者线程 负责生产商品 消费者线程 负责消费商品 当商品的数量为0的时候,消费者是不可能消费商品的 */ private static int count = 0;//库存 商品的剩余数量 private static final int FULL = 10;//生产者最多生产的商品数量 private static final String LOCK = "lock";//声明一个字符串对象,用来对象锁 //生产者 class Producer implements Runnable{ @Override public void run() { while (true){ synchronized (LOCK){ if (count == FULL){//已生产足够的商品 try { LOCK.wait();//使当前线程 进入等待状态 } catch (InterruptedException e) { e.printStackTrace(); } } count++;//生产商品 System.out.println(Thread.currentThread().getName() + "生产者生产,目前共有商品的个数: " + count); LOCK.notifyAll();//唤醒消费者线程 } } } } //消费者 class Consumer implements Runnable{ @Override public void run() { while (true){ synchronized (LOCK){ if(count == 0){//没库存了 try { LOCK.wait();//停止消费 等待 } catch (InterruptedException e) { e.printStackTrace(); } } count--;//消费商品 //消费一个商品之后,库存 就不满了,可以唤醒生产者线程了 LOCK.notifyAll(); System.out.println(Thread.currentThread().getName() + "消费者消费,目前共有商品的个数: " + count); } } } } public static void main(String[] args) { Test test = new Test(); Producer producer = test.new Producer();//创建生产者对象 Consumer consumer = test.new Consumer();//创建消费者对象 Thread t1 = new Thread(producer);// 生产者线程 Thread t2 = new Thread(consumer);// 消费者线程 t1.start(); t2.start(); } }
2、 使用3种不同的方式创建线程
package com.atguigu.create.c1; //创建多线程讲两种方式 // * 实现Runnable接口 // * 1 继承Thread类 // * 1.1新建一个新类型 继承Thread类 // 1.2重写run()方法 创建多个线程做的事 // 1.3 创建线程对象 // * 1.4调用start // * 2 实现Runnable接口 /* String name = java.lang.Thread.currentThread().getName();//获取当前线程名称 System.out.println("主线程name="+name);*/ public class Test { public static void main(String[] args) { // 1.创建线程对象 RabbitThread r = new RabbitThread(); r.start(); // while(true){ // System.out.println("乌龟跑"); //还可创建多个对象 RabbitThread r1 = new RabbitThread(); r1.start(); } }
package com.atguigu.create.c1; public class RabbitThread extends Thread { public void run(){ while (true){ System.out.println("兔子跑"); } } }
第二种:实现接口Runnable
package com.qiku.day22; //自定义类 实现Runnable接口 并重写run方法, public class Myhread2 implements Runnable{ @Override public void run(){ for (int i = 0; i < 100; i++) { System.out.println(i); } } }
package com.qiku.day22; public class MyThreadTest2 { public static void main(String[] args) { 创建该类的对象作为实参来构造Thread类型的对象, 然后使用Thread类型的对象调用start方法。 Myhread2 tt1 = new Myhread2(); Thread t1 = new Thread(tt1, "t1"); // Myhread2 tt2 = new Myhread2(); Thread t2 = new Thread(tt1, "t2"); t1.start(); t2.start(); System.out.println(t1.getName()); } }
第三种 匿名内部类
package com.qiku.day23; public class ThreadDemo02 { public static void main(String[] args) throws InterruptedException { Thread t1=new Thread(){ @Override public void run(){ for (int i = 0; i <=100; i++) { System.out.println(Thread.currentThread().getName()+" "+i); if (i==11){ Thread.yield();//让 cpu分配的时间片 回到就绪状态 } } } }; Thread t2=new Thread(){ @Override public void run(){ //打印1 - 100 之间的偶数 for (int i = 0; i <=100; i+=2) { System.out.println(Thread.currentThread().getName()+" "+i); // if (i==11){ // Thread.yield();//让 cpu分配的时间片 回到就绪状态 } } }; t1.setName("t1"); t2.setName("t2"); t1.start(); t2.start(); //主线程等待两个线程终止 希望main线程最后结束 // t1.join();//等待线程最后结束 t2.join(); t1.setPriority(10);//优先级过高 不一定先执行 只能说明获取时间片时间更长 System.out.println("t1的优先级"+t1.getPriority());//获取优先级 System.out.println("t2的优先级"+t2.getPriority());//获取优先级 } } 3、测试3种不同的线程池 创建一个线程池 当来任务时,如果有空余的线程,则分配给空余的 如果没有空余的 则创建一个新的线程 如果线程1 ,执行完毕 ,会继续接下个任务 老板资金雄厚,可以雇用无数个服务员: 多少个消费者都能同时服务 ExecutorService executorService = Executors.newCachedThreadPool(); 创建一个固定大小的线程池 线程池中线程的数量是固定的,如果有任务来的时候,线程池满了, 那就等着 老板资金一般,只雇用3个服务员: 第四个消费者来了,只能等着。。。。 创建只有一个线程的线程池 可以保证所有的任务按照指定的顺序执行 类似 队列 先进先出 FIFO 老板资金匮乏,自己服务员: 同一时间只能服务一个消费者,其他人只能等着。。。。
4、默写出线程的线程的生命周期,以及不同状态做什么事情?
使用new关键字创建线程对象 - 线程进入 新建状态 --- 不执行
调用start() - 线程进入 就绪状态(等待被分配时间片) --- 不执行
当线程分配到了时间时间片 - 线程进入 运行状态 ---- 执行run()方法
当时间片使用完毕之后,如果线程线程没结束 则回到 就绪状态(等待被分配时间片) --- 不执行
如果线程任务执行完毕 - 线程进入 消亡状态
在运行状态时,若发生导致阻塞事件(sleep(times) , wait() ,join() )
- 线程进入 阻塞状态(等待阻塞结束) -- 不执行
当阻塞状态结束时,则进入 就绪状态(等待被分配时间片) --- 不执行