赞
踩
多任务,进程,线程,多线程
进程:资源分配的最小单位。
进程是程序执行时的一个实例,即它是程序已经执行到课中程度的数据结构的汇集。从内核的观点看,进程的目的就是担当分配系统资源(CPU时间、内存等)的基本单位。
线程:程序执行的最小单位。
线程是CPU调度的最小单位(程序执行流的最小单元),它被包含在进程之中,是进程中的实际运作单元。一条线程是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
多线程
线程是程序中一个单一的顺序控制流程。进程内一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单元。在单一程序中同时运行多个想成完成不同的工作,称为多线程。
三种创建方式
继承Thread类
//创建线程方式一:继承Thread类,重写run()方法,调用start()开启线程 //总结:线程的开启不一定立即执行,由CPU调度执行 public class TestThread extends Thread{ @Override public void run() { //run()方法执行体 for (int i = 0; i < 200; i++) { System.out.println("我在学习==="); } } public static void main(String[] args) { TestThread thread = new TestThread(); //调用start()方法,开启线程 thread.start(); //main线程,主线程 for (int i = 0; i < 200; i++) { System.out.println("我在学习线程==="); } } }
//实现多线程同步下载图片 public class TestThread1 extends Thread { private String url;//网络图片地址 private String name;//保持的文件名 public TestThread1(String url, String name) { this.url = url; this.name = name; } @Override public void run() { WebDownLoader downLoader = new WebDownLoader(); downLoader.downLoader(url, name); System.out.println("下载了" + name); } public static void main(String[] args) { TestThread1 thread1 = new TestThread1("https://alifei03.cfp.cn/creative/vcg/800/version23/VCG41175510742.jpg", "1.jpg"); TestThread1 thread2 = new TestThread1("https://alifei04.cfp.cn/creative/vcg/800/version23/VCG211be3c9c31.jpg", "2.jpg"); TestThread1 thread3 = new TestThread1("https://tenfei01.cfp.cn/creative/vcg/800/version23/VCG21gic5474154.jpg", "3.jpg"); thread1.start(); thread2.start(); thread3.start(); } } //下载器 class WebDownLoader { //下载方法 public void downLoader(String url, String name) { try { FileUtils.copyURLToFile(new URL(url), new File(name)); } catch (IOException e) { e.printStackTrace(); } } }
实现Runnable接口
//创建线程方法二:实现Runnable接口,从写run()方法,执行线程需要丢入runnable接口实现类,调用start()方法 public class TestRunnable implements Runnable { @Override public void run() { //run方法线程体 for (int i = 0; i < 200; i++) { System.out.println("我在学习==="); } } public static void main(String[] args) { //创建runnable接口的实现类对象 TestRunnable testRunnable = new TestRunnable(); //创建线程对象,通过线程对象来开启我们的线程,代理 Thread thread = new Thread(testRunnable); thread.start(); for (int i = 0; i < 500; i++) { System.out.println("我在学习线程==="); } } }
//实现多线程同步下载图片 public class TestRunnable1 implements Runnable { private String url;//网络图片地址 private String name;//保持的文件名 public TestRunnable1(String url, String name) { this.url = url; this.name = name; } @Override public void run() { com.jun.lesson.WebDownLoader downLoader = new com.jun.lesson.WebDownLoader(); downLoader.downLoader(url, name); System.out.println("下载了" + name); } public static void main(String[] args) { TestRunnable1 thread1 = new TestRunnable1("https://alifei03.cfp.cn/creative/vcg/800/version23/VCG41175510742.jpg", "6.jpg"); TestRunnable1 thread2 = new TestRunnable1("https://alifei04.cfp.cn/creative/vcg/800/version23/VCG211be3c9c31.jpg", "4.jpg"); TestRunnable1 thread3 = new TestRunnable1("https://tenfei01.cfp.cn/creative/vcg/800/version23/VCG21gic5474154.jpg", "5.jpg"); new Thread(thread1).start(); new Thread(thread2).start(); new Thread(thread3).start(); } } //下载器 class WebDownLoader { //下载方法 public void downLoader(String url, String name) { try { FileUtils.copyURLToFile(new URL(url), new File(name)); } catch (IOException e) { e.printStackTrace(); } } }
实现Callable接口
//线程创建方式三:实现callable接口 public class TestCallable implements Callable<Boolean> { private String url;//网络图片地址 private String name;//保持的文件名 public TestCallable(String url, String name) { this.url = url; this.name = name; } @Override public Boolean call() throws Exception { DownLoader downLoader = new DownLoader(); downLoader.downLoader(url, name); System.out.println("下载了" + name); return true; } public static void main(String[] args) throws ExecutionException, InterruptedException { TestCallable t1 = new TestCallable("https://alifei03.cfp.cn/creative/vcg/800/version23/VCG41175510742.jpg", "7.jpg"); TestCallable t2 = new TestCallable("https://alifei04.cfp.cn/creative/vcg/800/version23/VCG211be3c9c31.jpg", "8.jpg"); TestCallable t3 = new TestCallable("https://tenfei01.cfp.cn/creative/vcg/800/version23/VCG21gic5474154.jpg", "9.jpg"); //创建执行任务 ExecutorService ser = Executors.newFixedThreadPool(3); //提交执行 Future<Boolean> r1 = ser.submit(t1); Future<Boolean> r2 = ser.submit(t2); Future<Boolean> r3 = ser.submit(t3); //获取结构 boolean rs1 = r1.get(); boolean rs2 = r2.get(); boolean rs3 = r3.get(); //关闭服务 ser.shutdown(); } } //下载器 class DownLoader { //下载方法 public void downLoader(String url, String name) { try { FileUtils.copyURLToFile(new URL(url), new File(name)); } catch (IOException e) { e.printStackTrace(); } } }
小结
继承Thread类
实现Runnable接口
多线程操作同一个对象(并发问题)
//多线程同时操作同一个对象 //买火车票 //发现问题:多个线程操作同一个资源的情况下,线程不安全 public class TestThread2 implements Runnable{ //票数 private int ticketNums = 10; @Override public void run() { while (true){ if(ticketNums<=0){ break; } //模拟延时 try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"-->拿到了第"+ticketNums--+"票"); } } public static void main(String[] args) { TestThread2 ticket = new TestThread2(); new Thread(ticket,"001").start(); new Thread(ticket,"002").start(); new Thread(ticket,"003").start(); } }
//模拟龟兔赛跑 public class Race implements Runnable{ //胜利者 private static String winner; @Override public void run() { for (int i = 0; i <= 100; i++) { //模拟兔子休息 if(Thread.currentThread().getName().equals("兔子") && i%10==0){ try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } //判断比赛是否结束 boolean flag = gameOver(i); //比赛结束停止程序 if(flag){ break; } System.out.println(Thread.currentThread().getName()+"-->跑了"+i+"步"); } } //判断是否完成比赛 private boolean gameOver(int steps){ //判断是否有胜利者 if(winner!=null){ return true; }else { if(steps>=100){ winner=Thread.currentThread().getName(); System.out.println("winner is" + winner); return true; } } return false; } public static void main(String[] args) { Race race = new Race(); new Thread(race,"兔子").start(); new Thread(race,"乌龟").start(); } }
实现Callable接口
public class StacticProxy { public static void main(String[] args) { You you = new You(); //new Thread(()-> System.out.println("我爱你")).start(); WeddingCompany weddingCompany = new WeddingCompany(you); weddingCompany.HappyMarry(); } } interface Marry { void HappyMarry(); } //真实角色 class You implements Marry { @Override public void HappyMarry() { System.out.println("要结婚了,好开心!"); } } //代理角色 class WeddingCompany implements Marry { private Marry target; public WeddingCompany(Marry target) { this.target = target; } @Override public void HappyMarry() { before(); this.target.HappyMarry(); after(); } public void before() { System.out.println("结婚前"); } public void after() { System.out.println("结婚后"); } }
静态代理模式总结:
好处:
λ希腊字母表中排序第十一位的字母
避免匿名内部类定义过多
其实质属于函数式编程的概念
(params) -> expression[表达式]
(params) -> statement[语句]
(params) -> {statements}
函数式接口定义:
public class TestLambda { //3,静态内部类 static class Like2 implements ILike { @Override public void lambda() { System.out.println("I like Lambda2"); } } public static void main(String[] args) { ILike like = new Like(); like.lambda(); like = new Like2(); like.lambda(); //4,局部内部类 class Like3 implements ILike { @Override public void lambda() { System.out.println("I like Lambda3"); } } like = new Like3(); like.lambda(); //5,匿名内部类,没有名称,必须借助接口或者父类 like = new ILike() { @Override public void lambda() { System.out.println("I like Lambda4"); } }; like.lambda(); //6,Lambda简化 like = () -> { System.out.println("I like Lambda5"); }; like.lambda(); } } //1,定义一个函数式接口 interface ILike { void lambda(); } //2,实现类 class Like implements ILike { @Override public void lambda() { System.out.println("I like Lambda1"); } }
总结:
线程的五大状态
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rmWWBGoA-1661529366476)(C:\Users\JunGao\Desktop\笔记\微信图片_20220825175721.jpg)]
创建状态
Thread t = new Thread()线程对象一旦创建就进入到了新生状态。
就绪状态
当调用start(),线程立即进入就绪状态,但不意味着立即调度执行。
阻塞状态
当调用sleep,wait或同步锁定时,线程进入阻塞状态,就是代码不往下执行,阻塞事件解除后,重新进入就绪状态,等待cpu调度执行。
运行状态
进入运行状态,线程才真正执行线程体的代码块。
死亡状态
线程中断或者结束,一旦进入死亡状态,就不能再次启动。
public class TestStop implements Runnable { //1,设置一个标识位 private boolean flag = true; @Override public void run() { int i = 0; while (flag) { System.out.println("run...Thread" + i++); } } //2,设置一个公开的方法停止线程,转换标识位 public void stop() { this.flag = false; } public static void main(String[] args) { TestStop testStop = new TestStop(); new Thread(testStop).start(); for (int i = 0; i < 100; i++) { System.out.println("main" + i); if (i == 90) { //调用stop方法切换标志位,让线程停止 testStop.stop(); System.out.println("线程该停止了"); } } } }
//模拟线程休眠 public class TestSleep implements Runnable{ //票数 private int ticketNums = 10; @Override public void run() { while (true){ if(ticketNums<=0){ break; } //模拟延时 try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"-->拿到了第"+ticketNums--+"票"); } } public static void main(String[] args) { TestSleep ticket = new TestSleep(); new Thread(ticket,"001").start(); new Thread(ticket,"002").start(); new Thread(ticket,"003").start(); } }
//模拟倒计时 public class TestSleep { public static void main(String[] args) { tenDown(); //打印当前系统时间 Date date = new Date(System.currentTimeMillis()); while (true) { try { Thread.sleep(1000); System.out.println(new SimpleDateFormat("HH:mm:ss").format(date)); date = new Date(System.currentTimeMillis()); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void tenDown() { int num = 10; while (true) { try { Thread.sleep(1000); System.out.println(num--); if (num <= 0) { break; } } catch (InterruptedException e) { e.printStackTrace(); } } } }
//模拟线程礼让 public class TestYield { public static void main(String[] args) { MyYield myYield = new MyYield(); new Thread(myYield,"a").start(); new Thread(myYield,"b").start(); } } class MyYield implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()+"线程开始"); Thread.yield();//线程礼让 System.out.println(Thread.currentThread().getName()+"线程停止"); } }
public class TestJoin implements Runnable{ @Override public void run() { for (int i = 0; i < 1000; i++) { System.out.println("vip线程"+i); } } public static void main(String[] args) throws InterruptedException { TestJoin testJoin = new TestJoin(); Thread thread = new Thread(testJoin); thread.start(); for (int i = 0; i < 500; i++) { if (i == 200){ thread.join(); } System.out.println("main"+i); } } }
//测试线程的状态 public class TestState { public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(()->{ for (int i = 0; i < 5; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("/"); }); //观察状态 Thread.State state = thread.getState(); System.out.println(state);//NWE //观察启动后 thread.start(); state = thread.getState(); System.out.println(state);//run while (state != Thread.State.TERMINATED){ Thread.sleep(100); state = thread.getState(); System.out.println(state); } } }
//测试线程优先级 public class TestPriority { public static void main(String[] args) { //主线程默认优先级 System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority()); MyPriority myPriority = new MyPriority(); Thread t1 = new Thread(myPriority); Thread t2 = new Thread(myPriority); Thread t3 = new Thread(myPriority); Thread t4 = new Thread(myPriority); //先设置优先级,再启动 t1.start(); t2.setPriority(1); t2.start(); t3.setPriority(4); t3.start(); t4.setPriority(Thread.MAX_PRIORITY); t4.start(); } } class MyPriority implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority()); } }
总结:优先级低只是意味着获得调度的概率低,并不是优先级低的就会被调用了,这都是看cpu的调度。
//测试守护线程 //上帝守护你 public class TestDaemon { public static void main(String[] args) { God god = new God(); Your your = new Your(); Thread thread = new Thread(god); thread.setDaemon(true);//默认是false表示是用户线程,正常的线程都是用户线程 thread.start();//上帝 守护线程启动 new Thread(your).start();//你 用户线程启动 } } //上帝 守护线程 class God implements Runnable{ @Override public void run() { while (true){ System.out.println("上帝保佑着你"); } } } //你 用户线程 class Your implements Runnable{ @Override public void run() { for (int i = 0; i < 36500; i++) { System.out.println("人生不过三万天,你的一生都要开心的活着!"); } System.out.println("===goodbye!world!==="); } }
并发:同一个对象被多个线程同时操作
//不安全买票 public class UnsafeBuyTicket { public static void main(String[] args) { BuyTicket station = new BuyTicket(); new Thread(station,"001").start(); new Thread(station,"002").start(); new Thread(station,"003").start(); } } class BuyTicket implements Runnable{ //票 private int ticketNums = 10; boolean flag = true;//外部停止方式 @Override public void run() { //买票 while (flag){ try { buy(); } catch (InterruptedException e) { e.printStackTrace(); } } } private void buy() throws InterruptedException { //判断是否有票 if(ticketNums<=0){ flag = false; return; } //模拟延时,放大问题的发生性 Thread.sleep(100); //买票 System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--); } }
Account{ int money;//余额 String name;//卡名 public Account(int money, String name) { this.money = money; this.name = name; } } //银行:模拟取款 class Drawing extends Thread{ Account account;//账户 int drawingMoney;//取钱 int nowMoney;//手里的钱 public Drawing(Account account,int drawingMoney,String name){ super(name); this.account = account; this.drawingMoney = drawingMoney; } //取钱 @Override public void run() { //判断有没有钱 if(account.money-drawingMoney<0){ System.out.println(Thread.currentThread().getName()+"钱不够,去不了"); return; } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //卡内余额 = 余额 - 你取得钱 account.money = account.money - drawingMoney; //你手里的钱 nowMoney = nowMoney + drawingMoney; System.out.println(account.name+"余额为:"+account.money); System.out.println(this.getName()+"手里的钱:"+nowMoney); } }
//线程不安全的集合 public class UnsafeList { public static void main(String[] args) { List<String> list = new ArrayList<>(); for (int i = 0; i < 10000; i++) { new Thread(()->{ list.add(Thread.currentThread().getName()); }).start(); } try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(list.size()); } }
//不安全买票 public class UnsafeBuyTicket { public static void main(String[] args) { BuyTicket station = new BuyTicket(); new Thread(station,"001").start(); new Thread(station,"002").start(); new Thread(station,"003").start(); } } class BuyTicket implements Runnable{ //票 private int ticketNums = 10; boolean flag = true;//外部停止方式 @Override public void run() { //买票 while (flag){ try { buy(); } catch (InterruptedException e) { e.printStackTrace(); } } } //synchronized 同步方法,锁的是this private synchronized void buy() throws InterruptedException { //判断是否有票 if(ticketNums<=0){ flag = false; return; } //模拟延时,放大问题的发生性 Thread.sleep(100); //买票 System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--); } }
//不安全的取钱 public class UnsafeBank { public static void main(String[] args) { //账户 Account account = new Account(100, "结婚基金"); Drawing you = new Drawing(account, 50, "you"); Drawing girlFriend = new Drawing(account, 100, "girlFriend"); you.start(); girlFriend.start(); } } //账户 class Account{ int money;//余额 String name;//卡名 public Account(int money, String name) { this.money = money; this.name = name; } } //银行:模拟取款 class Drawing extends Thread{ Account account;//账户 int drawingMoney;//取钱 int nowMoney;//手里的钱 public Drawing(Account account,int drawingMoney,String name){ super(name); this.account = account; this.drawingMoney = drawingMoney; } //取钱 @Override public void run() { //锁的对象就是变化的量,需要增删改查的对象 synchronized (account){ //判断有没有钱 if(account.money-drawingMoney<0){ System.out.println(Thread.currentThread().getName()+"钱不够,去不了"); return; } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //卡内余额 = 余额 - 你取得钱 account.money = account.money - drawingMoney; //你手里的钱 nowMoney = nowMoney + drawingMoney; System.out.println(account.name+"余额为:"+account.money); System.out.println(this.getName()+"手里的钱:"+nowMoney); } } }
//线程不安全的集合 public class UnsafeList { public static void main(String[] args) { List<String> list = new ArrayList<>(); for (int i = 0; i < 10000; i++) { new Thread(()->{ synchronized (list){ list.add(Thread.currentThread().getName()); } }).start(); } try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(list.size()); } }
//测试JUC安全类型的集合 public class TestJUC { public static void main(String[] args) { CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(); for (int i = 0; i < 1000; i++) { new Thread(()->{ list.add(Thread.currentThread().getName()); }).start(); } try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(list.size()); } }
//死锁:多个线程互相抱着对方需要的资源,然后形成僵持 public class DeadLock { public static void main(String[] args) { Makeup g1 = new Makeup(0,"灰姑娘"); Makeup g2 = new Makeup(1,"白雪公主"); g1.start(); g2.start(); } } //口红 class Lipstick{} //镜子 class Mirror{} class Makeup extends Thread{ //需要的资源只有一份,用static来保证只有一份 static Lipstick lipstick = new Lipstick(); static Mirror mirror = new Mirror(); int choice;//选择 String girlName;//使用化妆品的人 public Makeup(int choice,String girlName){ this.choice = choice; this.girlName = girlName; } @Override public void run() { try { makeup(); } catch (InterruptedException e) { e.printStackTrace(); } } //化妆,互相持有对方的锁,就是需要拿到对方的资源 private void makeup() throws InterruptedException { if(choice == 0){ synchronized (lipstick){ System.out.println(this.girlName+"口红"); Thread.sleep(1000); synchronized (mirror){ System.out.println(this.girlName+"镜子"); } } }else{ synchronized (mirror){ System.out.println(this.girlName+"镜子"); Thread.sleep(2000); synchronized (lipstick){ System.out.println(this.girlName+"口红"); } } } } }
互斥条件:一个资源每次只能被一个进程使用。
请求与保持条件:一个进程因请求资源而阻塞时,对以获得的资源保持不变。
不剥夺条件:进程以获得的资源,在未使用完之前,不能强行剥夺。
循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
上面列出了死锁的四个必要条件,我们只要想办法破其中的任意一个或多个条件就可以避免死锁的发生
public class DeadLock { public static void main(String[] args) { Makeup g1 = new Makeup(0,"灰姑娘"); Makeup g2 = new Makeup(1,"白雪公主"); g1.start(); g2.start(); } } //口红 class Lipstick{} //镜子 class Mirror{} class Makeup extends Thread{ //需要的资源只有一份,用static来保证只有一份 static Lipstick lipstick = new Lipstick(); static Mirror mirror = new Mirror(); int choice;//选择 String girlName;//使用化妆品的人 public Makeup(int choice,String girlName){ this.choice = choice; this.girlName = girlName; } @Override public void run() { try { makeup(); } catch (InterruptedException e) { e.printStackTrace(); } } //化妆,互相持有对方的锁,就是需要拿到对方的资源 private void makeup() throws InterruptedException { if(choice == 0){ synchronized (lipstick){ System.out.println(this.girlName+"口红"); Thread.sleep(1000); }synchronized (mirror){ System.out.println(this.girlName+"镜子"); } }else{ synchronized (mirror){ System.out.println(this.girlName+"镜子"); Thread.sleep(2000); }synchronized (lipstick){ System.out.println(this.girlName+"口红"); } } } }
//测试Lock锁 public class TestLock { public static void main(String[] args) { MyLock myLock = new MyLock(); new Thread(myLock).start(); new Thread(myLock).start(); new Thread(myLock).start(); } } class MyLock implements Runnable { int ticketNums = 10; //定义Lock锁 private final ReentrantLock lock = new ReentrantLock(); @Override public void run() { while (true) { try { lock.lock(); if (ticketNums > 0) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(ticketNums--); } else { break; } } finally { //释放锁 lock.unlock(); } } } }
应用场景:生产者和消费者问题
(生产者)->数据缓存区->(消费者)
这是一个线程同步问题,生产者和消费者共享同一个资源,并且生产者和消费者之间互相依赖,互为条件。
对于生产者,没有产品之前,要通知消费者等待,而生产了产品之后,有需要马上通知消费者消费。
对于消费者,在消费之后,要通知生产者已经结束消费,需要生产新的产品以供消费。
在生产者消费问题中,仅有synchronized是不够的
并发协作模型“生产者/消费者模式”—>管程法
//测试:生产者消费者模型-->利用缓冲区解决:管程法 //生产者,消费者,产品,缓冲区 public class TestPC { public static void main(String[] args) { SynContainer container = new SynContainer(); new Producer(container).start(); new Consumer(container).start(); } } //生产者 class Producer extends Thread { SynContainer container; public Producer(SynContainer container) { this.container = container; } @Override public void run() { for (int i = 0; i < 100; i++) { container.push(new Product(i)); System.out.println("生产了" + i + "产品"); } } } //消费者 class Consumer extends Thread { SynContainer container; public Consumer(SynContainer container) { this.container = container; } @Override public void run() { for (int i = 0; i < 100; i++) { container.pop(); System.out.println("消费了" + container.pop().id + "产品"); } } } //产品 class Product { int id;//产品编码 public Product(int id) { this.id = id; } } //缓冲区 class SynContainer { //缓冲区大小 Product[] products = new Product[10]; //缓冲区计数器 int count = 0; //生产者放入产品 public synchronized void push(Product product) { //如果缓冲区满了,就需要等待消费者消费 if (count == products.length) { //通知消费者消费,生产等待 try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //如果没有满,就需要放入产品 products[count] = product; count++; //通知消费者消费 this.notifyAll(); } //消费者消费产品 public synchronized Product pop() { //判断能否消费 if (count == 0) { //等待生产者生产,消费者等待 try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //如果可以消费 count--; Product product = products[count]; //消费完,通知生产者生产 this.notifyAll(); return product; } }
并发协作模型“生产者/消费者模式”—>信号灯法
//测试:生产者消费者模型-->信号灯法,标志位解决 public class TestPC2 { public static void main(String[] args) { TV tv = new TV(); new Player(tv).start(); new Watcher(tv).start(); } } //生产者 class Player extends Thread { TV tv; public Player(TV tv) { this.tv = tv; } @Override public void run() { for (int i = 0; i < 20; i++) { if (i%2==0){ this.tv.play("快乐大本营"); }else{ this.tv.play("抖音,记录美好生活"); } } } } //消费者 class Watcher extends Thread { TV tv; public Watcher(TV tv) { this.tv = tv; } @Override public void run() { for (int i = 0; i < 20; i++) { this.tv.watch(); } } } //产品-->节目 class TV { //演员表演,观众等待 //观众观看,演员等待 String voice;//表演节目 boolean flag = true;//标志位 //表演 public synchronized void play(String voice){ if(!flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("演员表演了:"+voice); //通知观众观看 this.notifyAll(); this.voice = voice; this.flag = !this.flag; } //观看 public synchronized void watch(){ if(flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("观众观看了:"+voice); //通知演员表演 this.notifyAll(); this.flag = !this.flag; } }
背景:经常创建和销毁,使用量特别大的资源,比如并发情况下的线程,对性能影响很大。
思路:提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回池中,可以避免频繁创建和销毁,实现重复利用。
好处:
JDK 5.0起提供了线程池相关API:ExecutorService和Executors
ExecutorService:真正的线程池接口。常见子类ThreadPoolExecutor
Executors:工具类,线程池的工具类,用于创建并返回不同类型的线程池
//测试线程池 public class TestPool { public static void main(String[] args) { //1.创建服务,创建线程池 //newFixedThreadPool 参数为:线程池大小 ExecutorService service = Executors.newFixedThreadPool(10); //执行 service.execute(new MyThread()); service.execute(new MyThread()); service.execute(new MyThread()); service.execute(new MyThread()); //2.关闭连接 service.shutdown(); } } class MyThread implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。