Java多线程
1.线程简介
进程:是执行程序的一次执行过程。
线程:是CPU调度和执行的单位,通常在一个进程中会包含若干个线程。
main()称之为主线程,为程序的入口,用于执行整个程序。
2.线程创建
方法1:
1 package X.Study.demo01; 2 3 //创建线程方式一:继承Thread类,重写run()方法,调用start开启线程 4 public class TestThread1 extends Thread { 5 @Override 6 public void run() { 7 //run方法线程体 8 for (int i = 0; i < 20; i++) { 9 System.out.println("我在看代码---" + i); 10 } 11 } 12 13 //main线程,主线程 14 public static void main(String[] args) { 15 16 //创建一个线程对象 17 TestThread1 testThread1 = new TestThread1(); 18 //调用start()方法开启线程 19 testThread1.start(); 20 21 22 for (int i = 0; i < 20; i++) { 23 System.out.println("我在学线程---" + i); 24 } 25 } 26 }
方法二:
1 package X.Study.demo01; 2 3 //实现runnable接口,重写run方法,执行线程需要丢入runnable接口实现类,调用start()方法 4 public class TestThread2 implements Runnable { 5 @Override 6 public void run() { 7 for (int i = 0; i < 20; i++) { 8 System.out.println("我在看代码" + i); 9 } 10 } 11 12 public static void main(String[] args) { 13 //创建runnable接口的实现类对象 14 TestThread2 testThread2 = new TestThread2(); 15 //创建线程对象,铜锅线程对象开启线程 16 Thread thread = new Thread(testThread2); 17 thread.start(); 18 19 20 for (int i = 0; i < 20; i++) { 21 System.out.println("我在学习" + i); 22 } 23 } 24 }
模拟龟兔赛跑
1 package X.Study.demo01; 2 3 4 public class Race implements Runnable { 5 6 private static String winner; 7 8 @Override 9 public void run() { 10 for (int i = 0; i <= 100; i++) { 11 //模拟兔子睡觉 12 if (Thread.currentThread().getName().equals("兔子")&&i%10==0){ 13 try { 14 Thread.sleep(200); 15 } catch (InterruptedException e) { 16 e.printStackTrace(); 17 } 18 } 19 20 boolean flag = gameOver(i); 21 if (flag) { 22 break; 23 } 24 System.out.println(Thread.currentThread().getName() + "跑了" + i + "步"); 25 } 26 27 } 28 29 public boolean gameOver(int step) { 30 if (winner != null) { 31 return true; 32 } 33 { 34 if (step >= 100) { 35 winner = Thread.currentThread().getName(); 36 System.out.println("winner is" + winner); 37 return true; 38 } 39 } 40 return false; 41 } 42 43 public static void main(String[] args) { 44 Race race = new Race(); 45 new Thread(race, "兔子").start(); 46 new Thread(race, "乌龟").start(); 47 48 } 49 }
3.静态代理
1 package X.Study.demo02; 2 3 public class StaticProxy { 4 public static void main(String[] args) { 5 You you = new You(); 6 WeddingCompany weddingCompany = new WeddingCompany(you); 7 weddingCompany.happyMarry(); 8 9 } 10 } 11 12 interface Marry { 13 void happyMarry(); 14 } 15 16 //真实角色,你去结婚 17 class You implements Marry { 18 @Override 19 public void happyMarry() { 20 System.out.println("我要结婚了"); 21 } 22 } 23 24 //代理公司,帮你准备结婚 25 class WeddingCompany implements Marry { 26 27 private Marry target; 28 29 public WeddingCompany(Marry target) { 30 this.target = target; 31 } 32 33 @Override 34 public void happyMarry() { 35 before(); 36 this.target.happyMarry(); 37 after(); 38 } 39 40 private void before() { 41 System.out.println("结婚前准备"); 42 } 43 44 private void after() { 45 System.out.println("结婚后收礼金"); 46 } 47 }
总结:
1.真实对象和代理对象都要实现同一个接口
2.代理对象要代理真实角色
4.Lambda表达式
1 package X.Study.demo03; 2 3 public class TestLamda { 4 5 //3.静态内部类 6 static class Like2 implements ILike { 7 @Override 8 public void lamda() { 9 System.out.println("I like lamda2"); 10 } 11 } 12 13 public static void main(String[] args) { 14 15 ILike like = new Like(); 16 like.lamda(); 17 18 like = new Like2(); 19 like.lamda(); 20 21 22 //4.局部内部类,放到main()方法里 23 class Like3 implements ILike { 24 @Override 25 public void lamda() { 26 System.out.println("I like lamda3"); 27 } 28 } 29 like = new Like3(); 30 like.lamda(); 31 32 33 //5.匿名内部类,没有类的名称,必须借助接口或者父类 34 like = new ILike() { 35 @Override 36 public void lamda() { 37 System.out.println("I like lamda4"); 38 } 39 }; 40 like.lamda(); 41 42 43 //6.用lamda简化 44 like=()->{ 45 System.out.println("I like lamda5"); 46 }; 47 like.lamda(); 48 49 50 } 51 52 53 } 54 55 //定义一个函数式接口:只包含一个抽象方法 56 interface ILike { 57 void lamda(); 58 } 59 60 //实现类 61 class Like implements ILike { 62 @Override 63 public void lamda() { 64 System.out.println("I like lamda"); 65 } 66 }
1 package X.Study.demo03; 2 3 public class TestLambda02 { 4 public static void main(String[] args) { 5 /*ILove love=new Love(); 6 love.love(20);*/ 7 8 ILove love = null; 9 /*//Lambda简化 10 love = (int a) -> { 11 System.out.println("I love you" + a); 12 }; 13 love.love(520);*/ 14 15 /*//简化1:去掉参数类型 16 love = (a) -> { 17 System.out.println("I love you" + a); 18 }; 19 love.love(521);*/ 20 21 /* //简化2:简化括号 22 love = a -> { 23 System.out.println("I love you" + a); 24 }; 25 love.love(521520);*/ 26 27 //简化3:去掉花括号 28 love = a -> 29 System.out.println("I love you" + a); 30 31 love.love(521520521); 32 } 33 34 35 interface ILove { 36 void love(int a); 37 } 38 39 class Love implements ILove { 40 @Override 41 public void love(int a) { 42 System.out.println("I love you" + a); 43 } 44 } 45 }
总结:
1.Lambda表达式只有一行代码的情况下才能简化成一行,如果有多行,需要用代码块包裹
2.前提接口为函数式接口
3.多个参数也可以去掉参数类型,要去掉就都去掉,必须加上括号
5.线程状态
5.1 线程停止
1 package X.Study.demo04; 2 3 //测试stop 4 //1.建议线程正常停止-->利用次数,不建议死循环 5 //2.建议使用标志位-->设置一个标志位 6 //3.不要使用stop或者destory等JDK不建议使用的方法 7 public class TestStop implements Runnable { 8 9 //设置一个标识位 10 private boolean flag = true; 11 12 @Override 13 public void run() { 14 int i = 0; 15 while (flag) { 16 System.out.println("run......Thread" + i++); 17 } 18 } 19 20 //设置一个公开的方法停止线程,转换标志位 21 public void stop() { 22 this.flag = false; 23 } 24 25 public static void main(String[] args) { 26 27 TestStop testStop = new TestStop(); 28 new Thread(testStop).start(); 29 30 for (int i = 0; i < 1000; i++) { 31 System.out.println("main" + i); 32 if (i == 900) { 33 //调用stop方法切换标志位,停止线程 34 testStop.stop(); 35 System.out.println("线程停止了"); 36 } 37 38 } 39 } 40 }
5.2 线程休眠
1 package X.Study.demo04; 2 3 //模拟网络延时:放大问题的发生性 4 public class TestSleep implements Runnable { 5 6 private int ticketNum = 10; 7 8 @Override 9 public void run() { 10 while (true) { 11 if (ticketNum <= 0) { 12 break; 13 } 14 try {//快捷键ctrl+alt+t 15 Thread.sleep(100); 16 } catch (InterruptedException e) { 17 e.printStackTrace(); 18 } 19 System.out.println(Thread.currentThread().getName() + "拿到了第---->" + ticketNum-- + "张票"); 20 } 21 } 22 23 public static void main(String[] args) { 24 TestSleep ticket = new TestSleep(); 25 new Thread(ticket, "小明").start(); 26 new Thread(ticket, "小红").start(); 27 new Thread(ticket, "小黑").start(); 28 } 29 }
1 package X.Study.demo04; 2 3 import javax.xml.crypto.Data; 4 import java.text.SimpleDateFormat; 5 import java.util.Date; 6 7 public class TestSleep02 { 8 9 public static void main(String[] args) { 10 /*try { 11 tenDown(); 12 } catch (InterruptedException e) { 13 e.printStackTrace(); 14 }*/ 15 16 //打印当前系统时间 17 Date startTime=new Date(System.currentTimeMillis());//获取当前系统时间 18 while(true){ 19 try { 20 Thread.sleep(1000); 21 System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime)); 22 startTime=new Date(System.currentTimeMillis());//更新当前时间 23 } catch (InterruptedException e) { 24 e.printStackTrace(); 25 } 26 27 28 } 29 } 30 //模拟倒计时 31 public static void tenDown() throws InterruptedException { 32 int num=10; 33 34 while (true){ 35 Thread.sleep(1000); 36 System.out.println(num--); 37 if(num<=0){ 38 break; 39 } 40 } 41 } 42 }
5.3 线程礼让
1 package X.Study.demo04; 2 3 //礼让不一定成功,看CPU心情 4 public class TestYeild { 5 public static void main(String[] args) { 6 MyThread myThread = new MyThread(); 7 new Thread(myThread,"前戏").start(); 8 new Thread(myThread,"PAPA").start(); 9 } 10 } 11 12 class MyThread implements Runnable{ 13 @Override 14 public void run() { 15 System.out.println(Thread.currentThread().getName()+"线程开始执行"); 16 Thread.yield();//礼让线程 17 System.out.println(Thread.currentThread().getName()+"线程停止执行"); 18 } 19 }
5.4 线程强制执行
1 package X.Study.demo04; 2 3 public class TestJoin implements Runnable { 4 @Override 5 public void run() { 6 for (int i = 0; i < 1000; i++) { 7 System.out.println("线程VIP来了-->" + i); 8 } 9 } 10 11 public static void main(String[] args) throws InterruptedException { 12 13 //启动线程,利用代理 14 TestJoin testJoin = new TestJoin(); 15 Thread thread = new Thread(testJoin); 16 thread.start(); 17 18 for (int i = 0; i < 500; i++) { 19 if (i == 200) { 20 thread.join();//插队 21 } 22 System.out.println("main" + i); 23 } 24 } 25 }
5.6 观测线程状态
1 package X.Study.demo04; 2 3 //观测线程状态 4 public class TestState { 5 public static void main(String[] args) throws InterruptedException { 6 Thread thread = new Thread(() -> { 7 try { 8 Thread.sleep(1000); 9 } catch (Exception e) { 10 e.printStackTrace(); 11 } 12 System.out.println("/////"); 13 }); 14 15 //观察状态 16 Thread.State state = thread.getState(); 17 System.out.println(state); 18 19 //观察启动后 20 thread.start();//启动线程 21 state = thread.getState(); 22 System.out.println(state); 23 24 while (state != Thread.State.TERMINATED) { 25 Thread.sleep(100); 26 state = thread.getState(); 27 System.out.println(state); 28 } 29 } 30 31 }
1 package X.Study.demo04; 2 3 //观测线程状态 4 public class TestState { 5 public static void main(String[] args) throws InterruptedException { 6 Thread thread = new Thread(() -> { 7 try { 8 Thread.sleep(1000); 9 } catch (Exception e) { 10 e.printStackTrace(); 11 } 12 System.out.println("/////"); 13 }); 14 15 //观察状态 16 Thread.State state = thread.getState(); 17 System.out.println(state); 18 19 //观察启动后 20 thread.start();//启动线程 21 state = thread.getState(); 22 System.out.println(state); 23 24 while (state != Thread.State.TERMINATED) { 25 Thread.sleep(100); 26 state = thread.getState(); 27 System.out.println(state); 28 } 29 } 30 31 }
5.7 线程优先级
1 package X.Study.demo04; 2 3 public class TestPriority { 4 5 public static void main(String[] args) { 6 //主线程默认优先级5 7 System.out.println(Thread.currentThread().getName() + "-->" + Thread.currentThread().getPriority()); 8 9 myPrioritor myPrioritor = new myPrioritor(); 10 Thread t1 = new Thread(myPrioritor); 11 Thread t2 = new Thread(myPrioritor); 12 Thread t3 = new Thread(myPrioritor); 13 Thread t4 = new Thread(myPrioritor); 14 Thread t5 = new Thread(myPrioritor); 15 Thread t6 = new Thread(myPrioritor); 16 //先设置优先级在启动 17 t1.start(); 18 19 t2.setPriority(1); 20 t2.start(); 21 22 t3.setPriority(10); 23 t3.start(); 24 25 t4.setPriority(8); 26 t4.start(); 27 28 t5.setPriority(2); 29 t5.start(); 30 31 t6.setPriority(3); 32 t6.start(); 33 } 34 35 36 } 37 38 class myPrioritor implements Runnable { 39 @Override 40 public void run() { 41 System.out.println(Thread.currentThread().getName() + "-->" + Thread.currentThread().getPriority()); 42 } 43 }
5.8 守护线程
1 package X.Study.demo04; 2 3 //测试守护线程 4 //上帝保佑你 5 public class TestDaemon { 6 public static void main(String[] args) { 7 God god = new God(); 8 You you = new You(); 9 10 Thread thread = new Thread(god); 11 thread.setDaemon(true);//默认是false,表示用户线程,正常的线程都是用户线程 12 thread.start();//上帝守护线程启动 13 14 new Thread(you).start();//你 用户线程启动 15 16 17 } 18 } 19 20 //上帝 21 class God implements Runnable { 22 @Override 23 public void run() { 24 while (true) { 25 System.out.println("上帝保佑着你"); 26 } 27 } 28 } 29 30 //你 31 class You implements Runnable { 32 @Override 33 public void run() { 34 for (int i = 0; i < 36500; i++) { 35 System.out.println("我每天开心地活着"); 36 } 37 System.out.println("sayGoodbye this World!"); 38 } 39 }
6 线程同步
队列+锁
6.1 线程不安全案例
1 package X.Study.syn; 2 3 //测试不安全的买票 4 //线程不安全,有负数 5 public class UnsafeBuyTickets { 6 public static void main(String[] args) { 7 ByTickets byTickets = new ByTickets(); 8 9 new Thread(byTickets, "小明").start(); 10 new Thread(byTickets, "小绿").start(); 11 new Thread(byTickets, "小黑").start(); 12 } 13 } 14 15 16 class ByTickets implements Runnable { 17 18 private int ticketNums = 10; 19 boolean flag = true;//设置一个标志位,用于线程停止 20 21 @Override 22 public void run() { 23 //买票 24 while (flag) { 25 try { 26 buy(); 27 } catch (Exception e) { 28 e.printStackTrace(); 29 } 30 } 31 32 } 33 34 //判断是否有票 35 private void buy() { 36 if (ticketNums <= 0) { 37 flag = false;//线程停止 38 return; 39 } 40 41 try { 42 Thread.sleep(100); 43 } catch (InterruptedException e) { 44 e.printStackTrace(); 45 } 46 //买票 47 System.out.println(Thread.currentThread().getName() + "拿到了第" + ticketNums-- + "张票"); 48 } 49 }
1 package X.Study.syn; 2 3 //模拟银行取款 4 //线程不安全,有负数 5 public class UnsafeBank { 6 public static void main(String[] args) { 7 Account account = new Account(100, "基金"); 8 9 Drawing You = new Drawing(account, 50, "你"); 10 Drawing GirlFriend = new Drawing(account, 100, "女人"); 11 12 You.start(); 13 GirlFriend.start(); 14 } 15 } 16 17 18 //账户 19 class Account { 20 int money;//余额 21 String name;//名字 22 23 public Account(int money, String name) { 24 this.money = money; 25 this.name = name; 26 } 27 } 28 29 //银行,模拟取款 30 class Drawing extends Thread { 31 Account account;//账户 32 int drawingMoney;//取了多少钱 33 int nowMoney;//现在有多少钱 34 35 public Drawing(Account account, int drawingMoney, String name) { 36 super(name); 37 this.drawingMoney = drawingMoney; 38 this.account = account; 39 } 40 41 //取钱 42 @Override 43 public void run() { 44 //判断是否有钱 45 if (account.money - drawingMoney < 0) { 46 System.out.println(Thread.currentThread().getName() + "钱不够了"); 47 return; 48 } 49 50 //sleep可以放大问题的发生性 51 try { 52 Thread.sleep(1000); 53 } catch (InterruptedException e) { 54 e.printStackTrace(); 55 } 56 //卡内余额 57 account.money = account.money - drawingMoney; 58 //你手里的钱 59 nowMoney = nowMoney + drawingMoney; 60 61 System.out.println(account.name + "余额为" + account.money); 62 63 System.out.println(this.getName() + "手里的钱:" + nowMoney); 64 65 } 66 }
6.2 同步方法及同步块
1 package X.Study.syn; 2 3 //测试买票 4 public class UnsafeBuyTickets { 5 public static void main(String[] args) { 6 ByTickets byTickets = new ByTickets(); 7 8 new Thread(byTickets, "小明").start(); 9 new Thread(byTickets, "小绿").start(); 10 new Thread(byTickets, "小黑").start(); 11 } 12 } 13 14 15 class ByTickets implements Runnable { 16 17 private int ticketNums = 10; 18 boolean flag = true;//设置一个标志位,用于线程停止 19 20 @Override 21 public void run() { 22 //买票 23 while (flag) { 24 try { 25 buy(); 26 } catch (Exception e) { 27 e.printStackTrace(); 28 } 29 } 30 31 } 32 33 //判断是否有票 34 private synchronized void buy() {//synchronized默认锁的是this. 35 if (ticketNums <= 0) { 36 flag = false;//线程停止 37 return; 38 } 39 40 try { 41 Thread.sleep(100); 42 } catch (InterruptedException e) { 43 e.printStackTrace(); 44 } 45 //买票 46 System.out.println(Thread.currentThread().getName() + "拿到了第" + ticketNums-- + "张票"); 47 } 48 }
1 package X.Study.syn; 2 3 //模拟银行取款 4 public class UnsafeBank { 5 public static void main(String[] args) { 6 Account account = new Account(100, "基金"); 7 8 Drawing You = new Drawing(account, 50, "你"); 9 Drawing GirlFriend = new Drawing(account, 100, "女人"); 10 11 You.start(); 12 GirlFriend.start(); 13 } 14 } 15 16 17 //账户 18 class Account { 19 int money;//余额 20 String name;//名字 21 22 public Account(int money, String name) { 23 this.money = money; 24 this.name = name; 25 } 26 } 27 28 //银行,模拟取款 29 class Drawing extends Thread { 30 Account account;//账户 31 int drawingMoney;//取了多少钱 32 int nowMoney;//现在有多少钱 33 34 public Drawing(Account account, int drawingMoney, String name) { 35 super(name); 36 this.drawingMoney = drawingMoney; 37 this.account = account; 38 } 39 40 //取钱 41 @Override 42 public void run() { 43 //判断是否有钱 44 //同步块 45 //锁的对象就是变化的量,需要增删改的对象 46 synchronized (account){ 47 if (account.money - drawingMoney < 0) { 48 System.out.println(Thread.currentThread().getName() + "钱不够了"); 49 return; 50 } 51 try { 52 Thread.sleep(1000); //sleep可以放大问题的发生性 53 } catch (InterruptedException e) { 54 e.printStackTrace(); 55 } 56 //卡内余额 57 account.money = account.money - drawingMoney; 58 //你手里的钱 59 nowMoney = nowMoney + drawingMoney; 60 61 System.out.println(account.name + "余额为" + account.money); 62 63 System.out.println(this.getName() + "手里的钱:" + nowMoney); 64 } 65 66 67 68 69 } 70 }
6.3 死锁
多个线程互相抱着对方需要的资源,然后形成僵持。
1 package X.Study.deadLock; 2 3 public class DeadLock { 4 public static void main(String[] args) { 5 MakeUP g1 = new MakeUP(0, "小绿"); 6 MakeUP g2 = new MakeUP(1, "小蓝"); 7 8 g1.start(); 9 g2.start(); 10 11 12 } 13 } 14 15 //口红 16 class Lipstick { 17 } 18 19 //镜子 20 class Mirror { 21 } 22 23 24 class MakeUP extends Thread { 25 //需要的资源,用static保证只有一份 26 static Lipstick lipstick = new Lipstick(); 27 static Mirror mirror = new Mirror(); 28 29 int choice;//选择 30 String girlName;//使用化妆品的人 31 32 MakeUP(int choice, String girlName) { 33 this.choice = choice; 34 this.girlName = girlName; 35 } 36 37 @Override 38 public void run() { 39 try { 40 makeup();//化妆 41 } catch (Exception e) { 42 e.printStackTrace(); 43 } 44 45 } 46 47 //化妆 48 private void makeup() { 49 if (choice == 0) { 50 synchronized (lipstick) {//获得口红的锁 51 System.out.println(this.girlName + "获得口红的锁"); 52 try { 53 Thread.sleep(1000); 54 } catch (InterruptedException e) { 55 e.printStackTrace(); 56 } 57 58 synchronized (mirror) {//一秒钟后,想获得镜子 59 System.out.println(this.girlName + "获得镜子的锁"); 60 } 61 } 62 } else { 63 synchronized (mirror) {//获得镜子的锁 64 System.out.println(this.girlName + "获得镜子的锁"); 65 try { 66 Thread.sleep(2000); 67 } catch (InterruptedException e) { 68 e.printStackTrace(); 69 } 70 71 synchronized (lipstick) {//两秒钟后,想获得口红 72 System.out.println(this.girlName + "获得口红的锁"); 73 } 74 75 } 76 77 78 } 79 } 80 }
两个人都需要获得对方的资源,程序执行会导致死锁
解决办法:把资源拿出对方的锁
1 private void makeup() { 2 if (choice == 0) { 3 synchronized (lipstick) {//获得口红的锁 4 System.out.println(this.girlName + "获得口红的锁"); 5 try { 6 Thread.sleep(1000); 7 } catch (InterruptedException e) { 8 e.printStackTrace(); 9 } 10 } 11 synchronized (mirror) {//一秒钟后,想获得镜子 12 System.out.println(this.girlName + "获得镜子的锁"); 13 } 14 } else { 15 synchronized (mirror) {//获得镜子的锁 16 System.out.println(this.girlName + "获得镜子的锁"); 17 try { 18 Thread.sleep(2000); 19 } catch (InterruptedException e) { 20 e.printStackTrace(); 21 } 22 } 23 24 synchronized (lipstick) {//两秒钟后,想获得口红 25 System.out.println(this.girlName + "获得口红的锁"); 26 } 27 } 28 }
6.4 lock锁
1 package X.Study.Gaoji; 2 3 import java.util.concurrent.locks.ReentrantLock; 4 5 public class TestLock { 6 public static void main(String[] args) { 7 TestLock1 testLock = new TestLock1(); 8 9 10 new Thread(testLock).start(); 11 new Thread(testLock).start(); 12 new Thread(testLock).start(); 13 } 14 } 15 16 class TestLock1 implements Runnable { 17 18 int ticketNums = 10; 19 //定义lock锁 20 private final ReentrantLock lock = new ReentrantLock(); 21 22 @Override 23 public void run() { 24 while (true) { 25 try { 26 lock.lock();//加锁 27 if (ticketNums > 0) { 28 try { 29 Thread.sleep(1000); 30 } catch (InterruptedException e) { 31 e.printStackTrace(); 32 } 33 System.out.println(ticketNums--); 34 } else { 35 break; 36 } 37 } finally { 38 lock.unlock(); 39 } 40 41 } 42 } 43 }
7.线程协作
7.1 生产者/消费者模型:管程法
1 package X.Study.Gaoji; 2 //测试:生产者/消费者模型-->利用缓冲区解决:管程法 3 4 //需要生产者,消费者,产品,缓冲区 5 public class TestPC { 6 public static void main(String[] args) { 7 SynContainer container = new SynContainer(); 8 9 new Productor(container).start(); 10 new Consumer(container).start(); 11 12 } 13 } 14 15 16 //生产者 17 class Productor extends Thread { 18 SynContainer container; 19 20 public Productor(SynContainer container) { 21 this.container = container; 22 } 23 //生产 24 25 @Override 26 public void run() { 27 for (int i = 0; i < 100; i++) { 28 System.out.println("生产了" + i + "只鸡"); 29 container.push(new Chicken(i)); 30 } 31 } 32 } 33 34 //消费者 35 class Consumer extends Thread { 36 SynContainer container; 37 38 public Consumer(SynContainer container) { 39 this.container = container; 40 } 41 42 //消费 43 44 @Override 45 public void run() { 46 for (int i = 0; i < 100; i++) { 47 System.out.println("消费了-->" + container.pop().id + "只鸡"); 48 } 49 } 50 } 51 52 //产品 53 class Chicken { 54 int id; 55 56 public Chicken(int id) { 57 this.id = id; 58 } 59 60 } 61 62 //缓冲区 63 class SynContainer { 64 //需要一个容器 65 Chicken[] chickens = new Chicken[10]; 66 67 //容器计数器 68 int count = 0; 69 70 //生产者放入产品 71 public synchronized void push(Chicken chicken) { 72 //如果容器满了,需要等待消费者消费 73 if (count == chickens.length) { 74 //通知消费者消费,生产等待 75 try { 76 this.wait(); 77 } catch (InterruptedException e) { 78 e.printStackTrace(); 79 } 80 } 81 //如果没有满,我们需要丢入产品 82 chickens[count] = chicken; 83 count++; 84 this.notifyAll(); 85 } 86 87 //消费者消费产品 88 public synchronized Chicken pop() { 89 //判断能否消费 90 if (count == 0) { 91 //等待生产者生产 92 try { 93 this.wait(); 94 } catch (InterruptedException e) { 95 e.printStackTrace(); 96 } 97 } 98 99 //如果可以消费 100 count--; 101 Chicken chicken = chickens[count]; 102 103 //拿走后,通知生产者生产 104 this.notifyAll();//解除等待 105 106 107 return chicken; 108 } 109 }
7.2 生产者/消费者模型:信号灯法
1 package X.Study.Gaoji; 2 3 //信号灯法:标志位解决 4 public class TestPC2 { 5 public static void main(String[] args) { 6 TV tv = new TV(); 7 8 new Player(tv).start(); 9 new Watcher(tv).start(); 10 } 11 } 12 13 14 //生产者:演员 15 class Player extends Thread { 16 TV tv; 17 18 public Player(TV tv) { 19 this.tv = tv; 20 } 21 22 @Override 23 public void run() { 24 for (int i = 0; i < 20; i++) { 25 if (i % 2 == 0) { 26 this.tv.play("明星大侦探播放中"); 27 } else { 28 this.tv.play("不好意思,推送广告中"); 29 } 30 } 31 } 32 } 33 34 //消费者:观众 35 class Watcher extends Thread { 36 TV tv; 37 38 public Watcher(TV tv) { 39 this.tv = tv; 40 } 41 42 @Override 43 public void run() { 44 for (int i = 0; i < 20; i++) { 45 tv.watch(); 46 } 47 } 48 49 50 } 51 52 //产品:节目 53 class TV { 54 //演员表演,观众等待 55 //观众观看,演员等待 56 String voice;//表演的节目 57 boolean flag = true;//标志位 58 59 //表演 60 public synchronized void play(String voice) { 61 if (!flag) { 62 try { 63 this.wait(); 64 } catch (InterruptedException e) { 65 e.printStackTrace(); 66 } 67 } 68 System.out.println("演员表演了" + voice); 69 //通知观众观看 70 this.notifyAll(); 71 this.voice = voice; 72 this.flag = !this.flag; 73 } 74 75 //观看 76 public synchronized void watch() { 77 if (flag) { 78 try { 79 this.wait(); 80 } catch (InterruptedException e) { 81 e.printStackTrace(); 82 } 83 } 84 System.out.println("观看了" + voice); 85 //通知演员表演 86 this.notifyAll(); 87 this.flag = !this.flag; 88 } 89 }
7.3 线程池
1 package X.Study.Gaoji; 2 3 import java.util.concurrent.Executor; 4 import java.util.concurrent.ExecutorService; 5 import java.util.concurrent.Executors; 6 7 public class TestPool { 8 public static void main(String[] args) { 9 //1.创建服务,创建线程池 10 ExecutorService service = Executors.newFixedThreadPool(10); 11 12 //2.执行 13 service.execute(new MyThread()); 14 service.execute(new MyThread()); 15 service.execute(new MyThread()); 16 service.execute(new MyThread()); 17 18 //3.关闭链接 19 service.shutdown(); 20 21 22 } 23 } 24 25 class MyThread implements Runnable { 26 @Override 27 public void run() { 28 System.out.println(Thread.currentThread().getName()); 29 } 30 }

浙公网安备 33010602011771号