大型网站建设企业名录模板,hao123网址之家官网电脑版,西安 微网站,英文网站用什么字体好3.7. Lambda表达式 为什么要使用lambda表达式 避免匿名内部类定义过多#xff1b;可以让代码看起来更简洁#xff1b;去掉一堆没有意义的代码#xff0c;只留下核心逻辑 属于函数式编程的概念#xff0c;格式 (params) - expression [表达式](params) - statement…3.7. Lambda表达式 为什么要使用lambda表达式 避免匿名内部类定义过多可以让代码看起来更简洁去掉一堆没有意义的代码只留下核心逻辑 属于函数式编程的概念格式 (params) - expression [表达式](params) - statement [语句](params) - {statements} 函数式接口 任何接口只有唯一一个抽象方法就是一个函数式接口对于函数式接口可以通过Lambda表达式来创建该接口的对象 测试 TestLambda.javapackage com.hzs.basic.multithread;/*** author Cherist Huan* version 1.0*/
public class TestLambda {// 2、静态内部类static class Like2 implements Ilike{Overridepublic void lambda() {System.out.println(Like--2);}}public static void main(String[] args) {Ilike like null;// 1、外部实现类1like new Like();like.lambda();// 2、静态内部类like new Like2();like.lambda();//3、局部内部类class Like3 implements Ilike{Overridepublic void lambda() {System.out.println(Like--3);}}like new Like3();like.lambda();//4、匿名内部类没有类的名称必须借助接口或父类like new Ilike() {Overridepublic void lambda() {System.out.println(Like--4);}};like.lambda();//5、用Lambda表达式like ()-{System.out.println(Like--5);};like.lambda();}
}// 1、定义一个函数式接口
interface Ilike{void lambda();
}// 2、外部实现类1class Like implements Ilike{Overridepublic void lambda() {System.out.println(Like--1);}
} a
3.8. 线程的状态5种 线程工包括5中状态 新建状态New线程对象被创建后就进入了新建状态。例如Thread thread new Thread(). 就绪状态Runnable也被称为“可执行状态”。线程对象被创建后其它线程调用了该对象的start()方法从而来启动该线程。例如thread.start()。处于就绪状态的线程随时可能被CPU调度执行。 运行状态Running线程获取CPU权限进行执行。需要注意的是线程只能从就绪状态进入到运行状态。 阻塞状态Blocked阻塞状态是线程因为某种原因放弃CPU使用权暂时停止运行。直到线程进入就绪状态才有机会转到运行状态。 阻塞的情况分3种 等待阻塞通过调用线程的wait()方法让线程等待某工作的完成同步阻塞线程在获取synchronized同步锁失败因为锁被其他线程所占用它会进入同步阻塞状态其他阻塞通过调用线程的sleep()或join()或发出了I/O请求时线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时线程重新转入就绪状态。 死亡状态Dead线程执行完了或者因异常退出了run()方法该线程结束生命周期。
3.9.线程同步 同步方法 synchronized关键字它包括synchronized方法和synchronized块 同步方法 public synchronized void method(int args){}synchronized方法控制对“对象”的访问每个对象对应一把锁每个synchronized方法都必须获得调用该方法的对象的锁才能执行否则线程会阻塞方法一旦执行就独占该锁指导该方法返回是释放锁后面被阻塞的线程才能获得这个锁继续执行。 缺陷若将一个大的方法声明为synchronized将会影响效率 同步块 同步块synchronized (Obj){} Obj称之为同步监视器 Obj可以是任何对象但是推荐使用共享资源作为同步监视器同步方法中无需指定同步监视器因为同步方法的同步监视器就是this就是这个对象本身或者是class反射 同步监视器的执行过程 1.第一个线程访问锁定同步监视器执行其中代码2.第二个线程访问发现同步监视器被锁定无法访问3.第一个线程访问完毕解锁同步监视器4.第二个线程访问发现同步监视器没有锁然后锁定并访问。 锁Obj例子 UnsafeList.java
package com.hzs.basic.multithread;
import java.util.ArrayList;
import java.util.List;/*** author Cherist Huan* version 1.0*/
public class UnsafeList {public static void main(String[] args) {ListString list new ArrayListString();for (int i 0; i 10000; i) {new Thread(()-{synchronized (list){list.add(Thread.currentThread().getName());}}).start();}// 获取线程数目boolean flag true;while(flag){if(Thread.activeCount() 2){flag false;System.out.println(list.size());}}}
}
3.10.死锁
产生死锁的4个必要条件
互斥条件一个资源每次只能被一个进程使用请求与保持条件一个进程因请求资源而阻塞时对已获得的资源保持不放不剥夺条件进程已获得的资源在未使用完之前不能强行剥夺循环等待条件若干进程之间形成一种头尾相接的循环等待资源关系
避免死锁只要破坏上面至少一个条件即可。
3.11.Lock锁 格式 class A{private final ReentrantLock lock new ReentrantLock();public void method(){lock.lock();try{//保证线程安全的代码}finally{lock.unlock();}}
}例子 package com.hzs.basic.multithread;
import java.util.concurrent.locks.ReentrantLock;
/*** author Cherist Huan* version 1.0*/
public class TestLock {public static void main(String[] args) {Ticket ticket new Ticket();new Thread(ticket).start();new Thread(ticket).start();new Thread(ticket).start();}
}class Ticket implements Runnable{private int ticketNum 10;private final ReentrantLock reentrantLock new ReentrantLock();Overridepublic void run() {while(true) {// 加锁reentrantLock.lock();try {if(ticketNum 0){Thread.sleep(100);System.out.println(ticketNum--);}else{break;}} catch (InterruptedException e) {e.printStackTrace();} finally {reentrantLock.unlock();}}}
} synchronized与Lock的对比 Lock是显示锁手动开启和关闭锁别忘记关闭锁synchronized是隐式锁出了作用域自动释放 Lock只有代码块锁synchronized有代码块锁和方法锁 使用Lock锁JVM将花费较少的时间来调度线程性能更好。并且具有更好的扩展性有很多子类例如:可重入锁 ReentrantLock 优先使用顺序 Lock 同步代码块已经进入了方法体分配了相应资源 同步方法方法体之外
3.12.线程通信
Java提供了几个方法解决线程之间的通信问题 wait()表示线程一直等待直到其他线程通知与sleep不同会释放锁wait(long timeout):指定等待的毫秒数notify():唤醒一个处于等待状态的线程notifyAll():唤醒同一个对象上所有调用wait()方法的线程优先级别高的线程优先调度。注意这些均是Object类的方法都只能在同步方法或者同步代码块中使用否则会抛出异常IllegalMonitorStateException
2. 等待唤醒机制这是多个线程间的一种协作机制。 谈到线程我们经常想到的是线程间的竞争race比如去争夺锁但这并不是故事的全部线程间也会有协作机制。 在一个线程满足某个条件时就进入等待状态wait() / wait(time) 等待其他线程执行完他们的指定代码过后再将其唤醒notify(); 或可以指定wait的时间等时间到了自动唤醒 在有多个线程进行等待时如果需要可以使用 notifyAll()来唤醒所有的等待线程。wait/notify 就是线程间的一种协作机制。
解决方式
方式一并发协作模型“生产者/消费者模式”--------管程法采用数据缓冲区方式二并发协作模型“生产者/消费者模式”--------信号灯法
为什么要处理线程间的通信 当我们需要多个线程来共同完成一件任务并且我们希望他们有规律的执行那么多线程之间需要一些通信机制可以协调它们的工作以此实现多线程共同操作一份数据。在同步的基础之上解决通信的问题 比如线程A用来生产包子的线程B用来吃包子的包子可以理解为同一资源线程A与线程B处理的动作一个是生产一个是消费此时B线程必须等到A线程完成后才能执行那么线程A与线程B之间就需要线程通信即—— 等待唤醒机制。
3.13.线程池 例子 package com.hzs.basic.multithread;import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** author Cherist Huan* version 1.0* note 线程池的使用*/
public class TestThreadPool {public static void main(String[] args) {// 1、创建ExecutorService executorService Executors.newFixedThreadPool(10);// 2、执行executorService.execute(new MyThread());executorService.execute(new MyThread());executorService.execute(new MyThread());// 3、关闭executorService.shutdown();}
}class MyThread implements Runnable{Overridepublic void run() {System.out.println(Thread.currentThread().getName());}
}
输出
pool-1-thread-2
pool-1-thread-1
pool-1-thread-32、线程池工作原理图 3、线程池执行流程
判断核心线程数判断任务能否加入到任务队列判断最大线程数量根据线程池的饱和策略除了任务是否丢弃任务