当前位置: 首页 > news >正文

定制网站建设提供商服务好质量好的app开发

定制网站建设提供商,服务好质量好的app开发,湛江seo哪家好,网站游戏网站开发设计菲律宾1.实现多线程 1.1简单了解多线程【理解】 是指从软件或者硬件上实现多个线程并发执行的技术。 具有多线程能力的计算机因有硬件支持而能够在同一时间执行多个线程#xff0c;提升性能。 1.2并发和并行【理解】 并行#xff1a;在同一时刻#xff0c;有多个指令在多个CPU上…1.实现多线程 1.1简单了解多线程【理解】 是指从软件或者硬件上实现多个线程并发执行的技术。 具有多线程能力的计算机因有硬件支持而能够在同一时间执行多个线程提升性能。 1.2并发和并行【理解】 并行在同一时刻有多个指令在多个CPU上同时执行。 这里的cpu就是比做我们人的大脑 并发在同一时刻有多个指令在单个CPU上交替执行。 这里的cpu就是比做我们人的大脑 1.3进程和线程【理解】 进程是正在运行的程序 独立性进程是一个能独立运行的基本单位同时也是系统分配资源和调度的独立单位 动态性进程的实质是程序的一次执行过程进程是动态产生动态消亡的 并发性任何进程都可以同其他进程一起并发执行 线程是进程中的单个顺序控制流是一条执行路径 单线程一个进程如果只有一条执行路径则称为单线程程序 多线程一个进程如果有多条执行路径则称为多线程程序 比如这里的360本身是一个进程而里面的功能是一个线程  1.4实现多线程方式一继承Thread类【应用】 方法介绍 方法名说明void run()在线程开启后此方法将被调用执行void start()使此线程开始执行Java虚拟机会调用run方法() 实现步骤 定义一个类MyThread继承Thread类 在MyThread类中重写run()方法 创建MyThread类的对象 启动线程 代码演示 package dxc;public class demo1 {public static void main(String[] args) {/*多线程的第一种启动的方式1.自己定义一个类继承Thread类2.重写里面run方法3. 创建子类的对象启动线程*/ThreadZi z1 new ThreadZi();ThreadZi z2 new ThreadZi();z1.setName(线程1);z2.setName(线程2);//开启线程z1.start();z2.start();} }package dxc;public class ThreadZi extends Thread {Overridepublic void run() {//线程执行的代码for (int i 0; i 100; i) {System.out.println(getName()hello);}} }两个小问题 为什么要重写run()方法 因为run()是用来封装被线程执行的代码 run()方法和start()方法的区别 run()封装线程执行的代码直接调用相当于普通方法的调用 start()启动线程然后由JVM调用此线程的run()方法 1.5实现多线程方式二实现Runnable接口【应用】 Thread构造方法 方法名说明Thread(Runnable target)分配一个新的Thread对象Thread(Runnable target, String name)分配一个新的Thread对象 实现步骤 定义一个类MyRunnable实现Runnable接口 在MyRunnable类中重写run()方法 创建MyRunnable类的对象 创建Thread类的对象把MyRunnable对象作为构造方法的参数 启动线程 代码演示 package dxc;public class demo2 {public static void main(String[] args) {/*多线程的第二种启动的方式1.定义一个类MyRunnable实现Runnable接口2.在MyRunnable类中重写run()方法3.创建MyRunnable类的对象4.创建Thread类的对象把MyRunnable对象作为构造方法的参数5.启动线程*/ //创建myRunnable类的对象表示多线程要执行的任务 MyRunnable m new MyRunnable();Thread t1 new Thread(m);t1.setName(线程1);Thread t2 new Thread(m);t2.setName(线程2);//启动线程t1.start();t2.start();} }package dxc;public class MyRunnable implements Runnable{Overridepublic void run() {for (int i 0; i 10; i) {//Thread.currentThread() 这个方法返回的是当前线程的对象//main方法创建了的线程对象t1和t2当t1调用start方法的时候Thread.currentThread()就表示是t1的线程对象System.out.println(Thread.currentThread().getName() hello);}} }1.6实现多线程方式三: 实现Callable接口【应用】 方法介绍 方法名说明V call()计算结果如果无法计算结果则抛出一个异常FutureTask(CallableV callable)创建一个 FutureTask一旦运行就执行给定的 CallableV get()如有必要等待计算完成然后获取其结果 实现步骤 定义一个类MyCallable实现Callable接口 在MyCallable类中重写call()方法 创建MyCallable类的对象 创建Future的实现类FutureTask对象把MyCallable对象作为构造方法的参数 创建Thread类的对象把FutureTask对象作为构造方法的参数 启动线程 再调用get方法就可以获取线程结束之后的结果。 代码演示 package dxc;import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask;public class demo3 {public static void main(String[] args) throws ExecutionException, InterruptedException {/*多线程的第三种实现方式特点可以获得多线程运行结果1.定义一个类MyCallable实现Callable接口2.在MyCallable类中重写call()方法 有返回值的表示多线程运行的结果3.创建MyCallable类的对象 表示多线程要执行的任务4.创建Future的实现类FutureTask对象把MyCallable对象作为构造方法的参数 作用管理多线程运行的结果5.创建Thread类的对象把FutureTask对象作为构造方法的参数 表示线程6.启动线程7.再调用get方法就可以获取线程结束之后的结果。*///创建MyCallable类的对象 表示多线程要执行的任务MyCallable m new MyCallable();//创建Future的实现类FutureTask对象把MyCallable对象作为构造方法的参数FutureTaskInteger f new FutureTask(m);//创建Thread类的对象把FutureTask对象作为构造方法的参数 作用管理多线程运行的结果Thread t1 new Thread(f);t1.start();//获取多线程的运行结果Integer result f.get();System.out.println(result);} }package dxc;import java.util.concurrent.Callable;/* 1.定义一个类MyCallable实现Callable接口2.在MyCallable类中重写call()方法*/ public class MyCallable implements CallableInteger {Overridepublic Integer call() throws Exception {int sum 0;for (int i 1; i 100; i) {sum i;}//返回值就表示线程运行完毕之后的结果return sum;} }三种实现方式的对比 实现Runnable、Callable接口 好处: 扩展性强实现该接口的同时还可以继承其他的类 缺点: 编程相对复杂不能直接使用Thread类中的方法 继承Thread类 好处: 编程比较简单可以直接使用Thread类中的方法 缺点: 可以扩展性较差不能再继承其他的类 1.7设置和获取线程名称【应用】 方法介绍 方法名说明void setName(String name)将此线程的名称更改为等于参数nameString getName()返回此线程的名称Thread currentThread()返回对当前正在执行的线程对象的引用 void setName(String name) 设置线程的名字构造方法也可以设置名字 使用构造方法去创建线程对象的时候可以使用有参构造来设置名字因为MyThread是我们自己写的类继承了父类Thread 父类的特有的方法构造方法我们不能使用只能重写父类的构造方法使用supr关键字来传递给父类 代码演示 package dxc02;public class MyThread extends Thread {public MyThread() {super();}public MyThread(String name) {super(name);}Overridepublic void run() {for (int i 0; i 10; i) {System.out.println(getName() 线程执行了 i);}} }package dxc02;public class demo1 {public static void main(String[] args) throws InterruptedException {/*String getName() 返回此线程的名称void setName(String name) 设置线程的名字构造方法也可以设置名字细节1、如果我们没有给线程设置名字线程也是有默认的名字的格式Thread-XX序号从0开始的2、如果我们要给线程设置名字可以用set方法进行设置也可以构造方法设置static Thread currentThread() 获取当前线程的对象细节当JVM虚拟机启动之后会自动的启动多条线程其中有一条线程就叫做main线程他的作用就是去调用main方法并执行里面的代码在以前我们写的所有的代码其实都是运行在main线程当中static void sleep(long time) 让线程休眠指定的时间单位为毫秒细节1、哪条线程执行到这个方法那么哪条线程就会在这里停留对应的时间2、方法的参数就表示睡眠的时间单位毫秒1 秒 1000毫秒3、当时间到了之后线程会自动的醒来继续执行下面的其他代码*///1.创建线程对象MyThread t1 new MyThread(小明);MyThread t2 new MyThread(小华);//2.开启线程t1.start();t2.start();//哪条线程执行到这个方法此时获取的就是哪条线程的对象Thread t Thread.currentThread();String name t.getName(); //因为是在main方法写的虚拟机会调用main方法里的线程所以线程的名字是mainSystem.out.println(name);System.out.println(111111111);Thread.sleep(5000);System.out.println(222222222);} }1.8线程休眠【应用】 相关方法 方法名说明static void sleep(long millis)使当前正在执行的线程停留暂停执行指定的毫秒数 代码演示 public class MyRunnable implements Runnable {Overridepublic void run() {for (int i 0; i 100; i) {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();} ​System.out.println(Thread.currentThread().getName() --- i);}} } public class Demo {public static void main(String[] args) throws InterruptedException {/*System.out.println(睡觉前);Thread.sleep(3000);System.out.println(睡醒了);*/ ​MyRunnable mr new MyRunnable(); ​Thread t1 new Thread(mr);Thread t2 new Thread(mr); ​t1.start();t2.start();} } 1.9线程优先级【应用】 抢占式调度体现的是随机性cpu不知道调用哪个线程  非抢占式调度是依次性轮流性Java默认是抢占式调度 线程调度 两种调度方式 分时调度模型所有线程轮流使用 CPU 的使用权平均分配每个线程占用 CPU 的时间片 抢占式调度模型优先让优先级高的线程使用 CPU如果线程的优先级相同那么会随机选择一个优先级高的线程获取的 CPU 时间片相对多一些 Java使用的是抢占式调度模型 随机性 假如计算机只有一个 CPU那么 CPU 在某一个时刻只能执行一条指令线程只有得到CPU时间片也就是使用权才可以执行指令。所以说多线程程序的执行是有随机性因为谁抢到CPU的使用权是不一定的 优先级相关方法 方法名说明final int getPriority()返回此线程的优先级final void setPriority(int newPriority)更改此线程的优先级线程默认优先级是5线程优先级的范围是1-10 代码演示 package dxc02;import dxc02.MyRunnable;public class demo2 {public static void main(String[] args) {/*setPriority(int newPriority) 设置线程的优先级final int getPriority() 获取线程的优先级*///创建线程要执行的参数对象MyRunnable mr new MyRunnable();//创建线程对象Thread t1 new Thread(mr,线程1);Thread t2 new Thread(mr,线程2);t1.setPriority(1);//设置那个线程的优先级高就说明该程序先运行的结束的概率大//java默认的优先级是5 //优先级越高抢占的cpu的机率就越大t2.setPriority(10);t1.start();t2.start();} }package dxc02;public class MyRunnable implements Runnable{Overridepublic void run() {for (int i 1; i 100; i) {System.out.println(Thread.currentThread().getName() --- i);}} }1.10守护线程【应用】 相关方法 方法名说明void setDaemon(boolean on)将此线程标记为守护线程当运行的线程都是守护线程时Java虚拟机将退出 代码演示 package dxc02;public class MyThread01 extends Thread{Overridepublic void run() {for (int i 1; i 10; i) {System.out.println(getName() i);}} }package dxc02;public class MyThread02 extends Thread{Overridepublic void run() {for (int i 1; i 100; i) {System.out.println(getName() i);}} }package dxc02;/*final void setDaemon(boolean on) 设置为守护线程细节当其他的非守护线程执行完毕之后守护线程会陆续结束通俗易懂当女神线程结束了那么备胎也没有存在的必要了,会陆续结束*/ public class demo3 {public static void main(String[] args) {// 创建线程对象MyThread01 t1 new MyThread01();MyThread02 t2 new MyThread02();t1.setName(女神);t2.setName(备胎);//把第二个线程设置为守护线程备胎线程t2.setDaemon(true);t1.start();t2.start();} }应用场景 当我们关闭了聊天窗口那么文件传输就没有必要执行下去了 1.11线程的生命周期 1.创建线程对象 是新建状态。 2.启动start变成就绪状态正在抢cpu的执行权还没有开始抢。 3.抢到cpu执行权就变成了运行状态 运行状态有可能被其他的线程抢走cpu执行权 如果抢走了又会到了就绪状态 4.如果说当前的线程把run方法所有的程序执行完成了线程就会死亡变成垃圾 5.如果调用sleep方法线程就会阻塞什么都干不了 6.当sleep方法时间到了就会回到就绪状态 2.线程同步 2.1卖票【应用】 案例需求 某电影院目前正在上映国产大片共有100张票而它有3个窗口卖票请设计一个程序模拟该电影院卖票 实现步骤 定义一个类SellTicket实现Runnable接口里面定义一个成员变量private int tickets 100; 在SellTicket类中重写run()方法实现卖票代码步骤如下 判断票数大于0就卖票并告知是哪个窗口卖的 卖了票之后总票数要减1 票卖没了线程停止 定义一个测试类SellTicketDemo里面有main方法代码步骤如下 创建SellTicket类的对象 创建三个Thread类的对象把SellTicket对象作为构造方法的参数并给出对应的窗口名称 启动线程 代码实现 2.2卖票案例的问题【理解】 package dxc03;public class Mythread extends Thread{//加上static关键字表示共享数据static int ticket0;//0-99Overridepublic void run() {while (true){if(ticket100){try {Thread.sleep(100);} catch (InterruptedException e) {throw new RuntimeException(e);}ticket;System.out.println(getName()卖出第ticket张票);}else{break;}}} }package dxc03; public class demo1 {public static void main(String[] args) {//某电影院目前正在上映国产大片共有100张票而它有3个窗口卖票请设计一个程序模拟该电影院卖票//1.创建线程对象Mythread t1new Mythread();Mythread t2new Mythread();Mythread t3new Mythread();t1.setName(窗口1);t2.setName(窗口2);t3.setName(窗口3);t1.start();t2.start();t3.start();// 程序运行的时候发现窗口1卖了第一张票窗口2竟然也能卖第一张票./*卖票出现了问题相同的票出现了多次出现了负数的票问题产生原因线程执行的随机性导致的,可能在卖票过程中丢失cpu的执行权,导致出现问题*/} }卖票出现了问题 相同的票出现了多次 出现了负数的票 问题产生原因 线程执行的随机性导致的,可能在卖票过程中丢失cpu的执行权,导致出现问题 分析①在开始抢到了cpu的执行权执行sleep方法阻塞状态的时候②抢到了cpu执行权同样sleep睡了此时③抢走了cpu执行权也sleep掉了此时被①抢到了执行权开始执行ticket准备执行打印语句但是cpu执行权被②抢到了此时的ticket变成了2然后到线程③的时候ticket变成了3. 记住一句话线程在执行代码的时候随时都可以被其他线程抢走cpu的执行权 所以三个线程最终打印的ticket的票数都是3这个就是重复票的由来线程执行时有随机性。 票数越界问题 解决方案 我们要把共享数据的代码锁起来只有当线程①的代码走完了就算是线程①进入堵塞状态其他线程也要等线程①走完代码才能抢夺cpu 2.3同步代码块解决数据安全问题【应用】 安全问题出现的条件 是多线程环境 有共享数据 有多条语句操作共享数据 如何解决多线程安全问题呢? 基本思想让程序没有安全问题的环境 怎么实现呢? 把多条语句操作共享数据的代码给锁起来让任意时刻只能有一个线程执行即可 Java提供了同步代码块的方式来解决 同步代码块格式 synchronized(任意对象) { 多条语句操作共享数据的代码 } synchronized(任意对象)就相当于给代码加锁了任意对象就可以看成是一把锁 同步的好处和弊端 好处解决了多线程的数据安全问题 弊端当线程很多时因为每个线程都会去判断同步上的锁这是很耗费资源的无形中会降低程序的运行效率 代码演示 package dxc03;import dxc02.MyThread;public class Mythread extends Thread {//加上static关键字表示共享数据static int tickets 0;;//0-99//锁对象保证多个线程用同一个锁//static Object obj new Object();Overridepublic void run() {while (true) {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}//解决方案synchronized (Mythread.class) { // 对可能有安全问题的代码加锁,多个线程必须使用同一把锁//t1进来后就会把这段代码给锁起来if (tickets 100) {tickets;System.out.println(getName() 卖出第 tickets 张票);} else {break;}}}}} //发现窗口1卖了第一张票竟然窗口2也能卖出票这是为什么线程安全问题看demo2解决方案/*卖票出现了问题 相同的票出现了多次 出现了负数的票 问题产生原因 线程执行的随机性导致的,可能在卖票过程中丢失cpu的执行权,导致出现问题*/ package dxc03; public class demo1 {public static void main(String[] args) {//某电影院目前正在上映国产大片共有100张票而它有3个窗口卖票请设计一个程序模拟该电影院卖票//1.创建线程对象Mythread t1new Mythread();Mythread t2new Mythread();Mythread t3new Mythread();t1.setName(窗口1);t2.setName(窗口2);t3.setName(窗口3);t1.start();t2.start();t3.start();// 程序运行的时候发现窗口1卖了第一张票窗口2竟然也能卖第一张票./*卖票出现了问题相同的票出现了多次出现了负数的票问题产生原因线程执行的随机性导致的,可能在卖票过程中丢失cpu的执行权,导致出现问题*/} }细节 1.synchronized这个不能写在循环外面如果写在外面会霸占整个循环只有线程①的票卖完了才轮到的线程②所以导致都是同一个窗口在卖票。 如果我们想把一个方法里面的所有的代码锁起来就没有必要使用同步代码块 2.4同步方法解决数据安全问题【应用】 同步方法的格式 同步方法就是把synchronized关键字加到方法上 修饰符 synchronized 返回值类型 方法名(方法参数) { 方法体 } 同步方法的锁对象是什么呢? this 静态同步方法 同步静态方法就是把synchronized关键字加到静态方法上 修饰符 static synchronized 返回值类型 方法名(方法参数) { 方法体 } 同步静态方法的锁对象是什么呢? 类名.class 代码演示 package dxc03;public class MyRunnable implements Runnable {int tickets 0;//不需要加static因为我们采用第二种方式实现多线程第二种方式是创建一个类MyRunnable实现Runnable接口//MyRunnable mr new MyRunnable(); 只需要创建一次Overridepublic void run() {//1.循环while (true) {try {Thread.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}//采用同步方法来写if (method()) {break;}}}/*方法是非静态的 锁对象就要用this修饰 这个this就是我们在测试类中创建的MyRunnable mr new MyRunnable();这个对象是用来表示多线程要执行的任务的*/private synchronized boolean method() {//2.同步代码块synchronized (MyRunnable.class) {if (tickets 100) {//3.判断共享数据是否到了末尾如果到了末尾return true;} else {//4.判断共享数据到了是否末尾如果没有到末尾tickets;System.out.println(Thread.currentThread().getName() 再卖票 tickets 张票);}}return false;} }package dxc03;public class demo2 {public static void main(String[] args) {//同步方法// 某电影院目前正在上映国产大片共有100张票而它有3个窗口卖票请设计一个程序模拟该电影院卖票//1.创建Myrunnable类对象表示多线程要执行的任务MyRunnable mr new MyRunnable();//2.创建Thread类对象表示线程,把Myrunnable对象作为构造方法的参数Thread t1 new Thread(mr);Thread t2 new Thread(mr);t1.setName(窗口1);t2.setName(窗口2);t1.start();t2.start();} }2.5Lock锁【应用】 当有线程执行代码之后锁就关闭了当线程出来之后锁就打开了我们没办法控制锁的开关。 虽然我们可以理解同步代码块和同步方法的锁对象问题但是我们并没有直接看到在哪里加上了锁在哪里释放了锁为了更清晰的表达如何加锁和释放锁JDK5以后提供了一个新的锁对象Lock Lock是接口不能直接实例化这里采用它的实现类ReentrantLock来实例化 - 代码演示 package dxc04;import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock;public class MyThread extends Thread {static int tikets 0;static Lock lock new ReentrantLock();//因为我们在demo1创建了多个线程对象所以这个Lock锁也会创建多个对象所以我们要用static修饰使其共享化/*void lock 获得锁void unlock() 释放锁*/Overridepublic void run() {//1.循环while (true) {try {Thread.sleep(10);} catch (InterruptedException e) {throw new RuntimeException(e);}lock.lock(); // 获得锁//2.同步代码块try {if (tikets 100) {break;} else {Thread.sleep(10);tikets;System.out.println(Thread.currentThread().getName() 卖出第 tikets 张票);}} catch (InterruptedException e) {throw new RuntimeException(e);} finally {lock.unlock();}}} } package dxc04;public class demo1 {//利用Lock方法public static void main(String[] args) {//1.创建线程对象MyThread t1 new MyThread();MyThread t2 new MyThread();t1.setName(窗口1);t2.setName(窗口2);//2.启动线程t1.start();t2.start();} }分析 如果抢到的都是线程1最终  走到100会break掉此时的锁还没有关闭所以我们用finally关键词不管怎么样finally里的代码都会执行 2.6死锁【理解】 概述 线程死锁是指由于两个或者多个线程互相持有对方所需要的资源导致这些线程处于等待状态无法前往执行 什么情况下会产生死锁 资源有限 同步嵌套 代码演示 public class Demo {public static void main(String[] args) {Object objA new Object();Object objB new Object();new Thread(()-{while(true){synchronized (objA){//线程一synchronized (objB){System.out.println(小康同学正在走路);}}}}).start();new Thread(()-{while(true){synchronized (objB){//线程二synchronized (objA){System.out.println(小薇同学正在走路);}}}}).start();} } 3.生产者消费者 3.1生产者和消费者模式概述【应用】 概述 生产者消费者模式是一个十分经典的多线程协作的模式弄懂生产者消费者问题能够让我们对多线程编程的理解更加深刻。 所谓生产者消费者问题实际上主要是包含了两类线程 一类是生产者线程用于生产数据 一类是消费者线程用于消费数据 为了解耦生产者和消费者的关系通常会采用共享的数据区域就像是一个仓库 生产者生产数据之后直接放置在共享数据区中并不需要关心消费者的行为 消费者只需要从共享数据区中去获取数据并不需要关心生产者的行为 Object类的等待和唤醒方法 方法名说明void wait()导致当前线程等待直到另一个线程调用该对象的 notify()方法或 notifyAll()方法void notify()唤醒正在等待对象监视器的单个线程void notifyAll()唤醒正在等待对象监视器的所有线程 3.2生产者和消费者案例【应用】 案例需求 桌子类(Desk)定义表示包子数量的变量,定义锁对象变量,定义标记桌子上有无包子的变量 生产者类(Cooker)实现Runnable接口重写run()方法设置线程任务 1.判断是否有包子,决定当前线程是否执行 2.如果有包子,就进入等待状态,如果没有包子,继续执行,生产包子 3.生产包子之后,更新桌子上包子状态,唤醒消费者消费包子 消费者类(Foodie)实现Runnable接口重写run()方法设置线程任务 1.判断是否有包子,决定当前线程是否执行 2.如果没有包子,就进入等待状态,如果有包子,就消费包子 3.消费包子后,更新桌子上包子状态,唤醒生产者生产包子 测试类(Demo)里面有main方法main方法中的代码步骤如下 创建生产者线程和消费者线程对象 分别开启两个线程 消费者等待如果先是消费者抢到cpu执行发现桌子上没有面条就会wait等待cpu的执行权就一定会被生产者抢到生产者做完了面条放在桌子上面此时的消费者还处于wait状态生产者就会通知一下notifyAll消费者唤醒 生产者等待一开始是生产者抢到了cpu执行权做完了面条放在桌子上然后通知一下消费者但是又被生产者抢到了cpu执行器此时生产者进入等待模式等待消费者抢到cpu执行器 代码实现 package dxc05;public class Cook extends Thread {/** 1. 循环* 2. 同步代码块* 3. 判断共享数据是否到了末尾到了末尾* 4. 判断共享数据是否到了末尾没有到末尾执行核心逻辑* */Overridepublic void run() {//1. 循环while (true) {// 2. 同步代码块synchronized (Desk.lock) {//3. 判断共享数据是否到了末尾到了末尾if (Desk.count 0) {break;} else {// 4. 判断共享数据是否到了末尾没有到末尾执行核心逻辑//判断桌子上是否有食物if (Desk.foodFlag 1) {//如果有就等待try {Desk.lock.wait();//让线程和当前的锁对象进行绑定 到时候唤醒的是所有绑定锁对象的线程} catch (InterruptedException e) {throw new RuntimeException(e);}} else {//如果没有就制作食物System.out.println(厨师做了一碗面条);//修改桌子上食物状态Desk.foodFlag 1;//叫醒等待的消费者开吃Desk.lock.notifyAll();}}}}} }package dxc05;import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock;public class Desk {/** 作用控制生产者和消费者的执行** *///是否有面条 0没有面条 1有面条public static int foodFlag 0;//总个数public static int count 10;//锁对象public static Lock lock new ReentrantLock(); }package dxc05;/** 1. 循环* 2. 同步代码块* 3. 判断共享数据是否到了末尾到了末尾* 4. 判断共享数据是否到了末尾没有到末尾执行核心逻辑* */ public class Foodie extends Thread {Overridepublic void run() {//1. 循环while (true) {// 2. 同步代码块synchronized (Desk.lock) {//3. 判断共享数据是否到了末尾到了末尾if (Desk.count 0) {//10碗面条吃完了就停止break;} else {// 4. 判断共享数据是否到了末尾没有到末尾执行核心逻辑//判断桌子上是否有食物if (Desk.foodFlag 1) {//如果有就开吃//把吃的总数-1Desk.count--;System.out.println(吃货在吃面条还能再吃 Desk.count 碗);//吃完之后唤醒厨师继续做Desk.lock.notifyAll();//唤醒绑定锁对象的所有线程//修改桌子的状态Desk.foodFlag 0;} else {//如果没有就等待try {Desk.lock.wait();//让当前线程跟锁进行绑定} catch (InterruptedException e) {throw new RuntimeException(e);}}}}}} }package dxc05; /*** 需求完成生产者和消费者等待唤醒机制的代码* 实现线程轮流交替执行的效果** */public class Test {public static void main(String[] args) {//创建线程的对象Cook c new Cook();Foodie f new Foodie();//给线程设置名字c.setName(厨师);f.setName(吃货);//开启线程c.start();f.start();} }3.3生产者和消费者案例优化【应用】 需求 将Desk类中的变量,采用面向对象的方式封装起来 生产者和消费者类中构造方法接收Desk类对象,之后在run方法中进行使用 创建生产者和消费者线程对象,构造方法中传入Desk类对象 开启两个线程 代码实现 public class Desk {//定义一个标记//true 就表示桌子上有汉堡包的,此时允许吃货执行//false 就表示桌子上没有汉堡包的,此时允许厨师执行//public static boolean flag false;private boolean flag;//汉堡包的总数量//public static int count 10;//以后我们在使用这种必须有默认值的变量// private int count 10;private int count;//锁对象//public static final Object lock new Object();private final Object lock new Object();public Desk() {this(false,10); // 在空参内部调用带参,对成员变量进行赋值,之后就可以直接使用成员变量了}public Desk(boolean flag, int count) {this.flag flag;this.count count;}public boolean isFlag() {return flag;}public void setFlag(boolean flag) {this.flag flag;}public int getCount() {return count;}public void setCount(int count) {this.count count;}public Object getLock() {return lock;}Overridepublic String toString() {return Desk{ flag flag , count count , lock lock };} }public class Cooker extends Thread {private Desk desk;public Cooker(Desk desk) {this.desk desk;} // 生产者步骤 // 1判断桌子上是否有汉堡包 // 如果有就等待如果没有才生产。 // 2把汉堡包放在桌子上。 // 3叫醒等待的消费者开吃。Overridepublic void run() {while(true){synchronized (desk.getLock()){if(desk.getCount() 0){break;}else{//System.out.println(验证一下是否执行了);if(!desk.isFlag()){//生产System.out.println(厨师正在生产汉堡包);desk.setFlag(true);desk.getLock().notifyAll();}else{try {desk.getLock().wait();} catch (InterruptedException e) {e.printStackTrace();}}}}}} }public class Foodie extends Thread {private Desk desk;public Foodie(Desk desk) {this.desk desk;}Overridepublic void run() { // 1判断桌子上是否有汉堡包。 // 2如果没有就等待。 // 3如果有就开吃 // 4吃完之后桌子上的汉堡包就没有了 // 叫醒等待的生产者继续生产 // 汉堡包的总数量减一//套路://1. while(true)死循环//2. synchronized 锁,锁对象要唯一//3. 判断,共享数据是否结束. 结束//4. 判断,共享数据是否结束. 没有结束while(true){synchronized (desk.getLock()){if(desk.getCount() 0){break;}else{//System.out.println(验证一下是否执行了);if(desk.isFlag()){//有System.out.println(吃货在吃汉堡包);desk.setFlag(false);desk.getLock().notifyAll();desk.setCount(desk.getCount() - 1);}else{//没有就等待//使用什么对象当做锁,那么就必须用这个对象去调用等待和唤醒的方法.try {desk.getLock().wait();} catch (InterruptedException e) {e.printStackTrace();}}}}}} }public class Demo {public static void main(String[] args) {/*消费者步骤1判断桌子上是否有汉堡包。2如果没有就等待。3如果有就开吃4吃完之后桌子上的汉堡包就没有了叫醒等待的生产者继续生产汉堡包的总数量减一*//*生产者步骤1判断桌子上是否有汉堡包如果有就等待如果没有才生产。2把汉堡包放在桌子上。3叫醒等待的消费者开吃。*/Desk desk new Desk();Foodie f new Foodie(desk);Cooker c new Cooker(desk);f.start();c.start();} } 3.4阻塞队列基本使用【理解】 阻塞队列继承结构 常见BlockingQueue: ArrayBlockingQueue: 底层是数组,有界 LinkedBlockingQueue: 底层是链表,无界.但不是真正的无界,最大为int的最大值 BlockingQueue的核心方法: put(anObject): 将参数放入队列,如果放不进去会阻塞 take(): 取出第一个数据,取不到会阻塞 代码示例 public class Demo02 {public static void main(String[] args) throws Exception {// 创建阻塞队列的对象,容量为 1ArrayBlockingQueueString arrayBlockingQueue new ArrayBlockingQueue(1);// 存储元素arrayBlockingQueue.put(汉堡包);// 取元素System.out.println(arrayBlockingQueue.take());System.out.println(arrayBlockingQueue.take()); // 取不到会阻塞System.out.println(程序结束了);} } 3.5阻塞队列实现等待唤醒机制【理解】 案例需求 生产者类(Cooker)实现Runnable接口重写run()方法设置线程任务 1.构造方法中接收一个阻塞队列对象 2.在run方法中循环向阻塞队列中添加包子 3.打印添加结果 消费者类(Foodie)实现Runnable接口重写run()方法设置线程任务 1.构造方法中接收一个阻塞队列对象 2.在run方法中循环获取阻塞队列中的包子 3.打印获取结果 测试类(Demo)里面有main方法main方法中的代码步骤如下 创建阻塞队列对象 创建生产者线程和消费者线程对象,构造方法中传入阻塞队列对象 分别开启两个线程 代码实现 public class Cooker extends Thread {private ArrayBlockingQueueString bd;public Cooker(ArrayBlockingQueueString bd) {this.bd bd;} // 生产者步骤 // 1判断桌子上是否有汉堡包 // 如果有就等待如果没有才生产。 // 2把汉堡包放在桌子上。 // 3叫醒等待的消费者开吃。Overridepublic void run() {while (true) {try {bd.put(汉堡包);System.out.println(厨师放入一个汉堡包);} catch (InterruptedException e) {e.printStackTrace();}}} }public class Foodie extends Thread {private ArrayBlockingQueueString bd;public Foodie(ArrayBlockingQueueString bd) {this.bd bd;}Overridepublic void run() { // 1判断桌子上是否有汉堡包。 // 2如果没有就等待。 // 3如果有就开吃 // 4吃完之后桌子上的汉堡包就没有了 // 叫醒等待的生产者继续生产 // 汉堡包的总数量减一//套路://1. while(true)死循环//2. synchronized 锁,锁对象要唯一//3. 判断,共享数据是否结束. 结束//4. 判断,共享数据是否结束. 没有结束while (true) {try {String take bd.take();System.out.println(吃货将 take 拿出来吃了);} catch (InterruptedException e) {e.printStackTrace();}}} }public class Demo {public static void main(String[] args) {ArrayBlockingQueueString bd new ArrayBlockingQueue(1);Foodie f new Foodie(bd);Cooker c new Cooker(bd);f.start();c.start();} } package dxc06;import java.util.concurrent.ArrayBlockingQueue;public class Foodie extends Thread {ArrayBlockingQueueString queue;public Foodie(ArrayBlockingQueueString queue) {this.queue queue;}Overridepublic void run() {while (true) {//不断从阻塞队列中获取面条try {String food queue.take();System.out.println(吃货吃掉了 food);/*细节我们在控制台看到的了连续的吃货或者厨师打印的语句是因为打印语句写在了锁对象的外面导致的本质还是吃一个生产一个*/} catch (InterruptedException e) {throw new RuntimeException(e);}}} }package dxc06;import java.util.concurrent.ArrayBlockingQueue;public class Cook extends Thread{ArrayBlockingQueueString queue;public Cook(ArrayBlockingQueueString queue) {this.queue queue;}Overridepublic void run() {while (true){//不断的把面条放到阻塞队列当中try {queue.put(面条);System.out.println(厨师放了一碗面条);} catch (InterruptedException e) {throw new RuntimeException(e);}}} }package dxc06;import java.util.concurrent.ArrayBlockingQueue;public class Tets {public static void main(String[] args) {/*** 需求利用阻塞队列完成生产者和消费者等待唤醒机制的代码* 细节* 生产者和消费者必须使用同一个阻塞队列** *///1.创建阻塞队列的对象ArrayBlockingQueueString queue new ArrayBlockingQueue(1);//这里的1是队列的大小最多每次放一碗面进入队列//2.创建生产者和消费者线程对象Cook cook new Cook(queue);Foodie foodie new Foodie(queue);//3.启动线程cook.start();foodie.start();} }4.线程的6种状态
http://www.zqtcl.cn/news/415499/

相关文章:

  • 培训网站模板免费网站建设投标书
  • 常德市建设局网站用tornado做网站
  • 网站快速排名优化报价现在最流行的网站开发工具
  • 支付公司网站建设会计分录合肥房产信息网官网
  • 镜像网站能否做google排名宝丰网站制作公司
  • 中国公路建设协会网站网站建设 业务培训
  • 原创文章网站开发教程安徽网站建设获客企业
  • 企业网站后台怎么做南京微网站开发
  • 网站seo在线优化广告策划书的格式
  • 网站解析怎么设置三北防护林体系建设网站
  • 长沙高端网站建设公司wordpress分享缩略图
  • 支付网站建设费管理咨询公司取名
  • dw网站制作的一般流程wordpress 分类列表页
  • 重庆技术支持 网站建设公司wordpress挂黑页
  • 2网站建设类似wordpress
  • 特别酷炫网站惠州的服装网站建设
  • 网站右侧悬浮代码网站新闻前置审批
  • 2015网站建设十堰网站优化排名
  • 营销网站的优点番禺人才网最新招聘市场在哪里?
  • 企业网站建站模板自己做网站网站资源哪里来
  • 接入服务商网站备案管理系统技术规范要求郴州网站建设软件定制开发制作
  • 温州做网站公司哪家好购物网站的基本功能
  • 网站建设网站建设教程建设糖果网站的好处有哪些
  • 松原手机网站开发wordpress数据库设计优缺点
  • 惠州建设工程造价管理站网站中国海洋大学站群网站建设
  • 怎么做网站里面的模块太原做网络推广
  • 网站关键词排名优化应该怎么做wordpress实惠主机
  • 服装 营销型网站案例网站建设资料需要公司提交的吗
  • 网站权重高 做别的关键词怎么查看网站是否被百度收录
  • 沈阳网站开发培训多少钱广州做网站的公司哪家好