多线程-静态代理-Lambda表达式
文章目录
- 多线程
- 进程和线程 (Process and Thread)
- 线程
- 实现线程的三种方式
- 继承Thread类
- 实现Runable接口
- 实现Callable接口
- 静态代理
- Thread底层实现方式
- Lamda表达式
- lamda进化过程
- lamda简化过程
- 线程操作
- 线程状态
- 线程状态观测
- 线程停止
- 线程停止为什么不推荐使用stop()和distory()方法?
- 线程休眠_sleep
- 线程礼让_yield
- 线程强制执行_Join
- 线程优先级_priority
- 守护线程_deamon
- 线程同步
- 同步方法,同步代码块
- 死锁
- Lock锁
- 线程通信
- 管程法
- 信号灯法
- 线程池
多线程
进程和线程 (Process and Thread)
- 程序,程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念
- 进程,进程是执行程序的一次执行过程,它是一个动态的概念,是系统资源分配的单位
- 线程,通常一个进程可以包含若干个线程,当然一个进程至少有一个线程,线程是cpu调度和执行的单位
- 很多多线程是模拟出来的,真正的多线程是指有多个cpu,即多核.
线程
- 线程就是独立的执行路径
- 在程序运行时,即使没有自己创建线程,后台也会有多个线程,如主线程、gc线程
- main()称为主线程,为系统的入口,用于执行整个程序
- 在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与操作系统紧密相关的,先后顺序是不能人为干涉的.
- 对同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制
- 每个线程在自己的工作内存交互,内存控制不当会造成数据不一致
- 线程会带来额外开销,如cpu调度时间,并发控制开销
实现线程的三种方式
- 避免单继承局限性,推荐使用Runnable接口实现
继承Thread类
/*** 多线程实现一: 1. 继承Thread类.* 2.重写run方法,编写线程执行体* 3.创建线程对象,调用start方法启动线程** 注: 线程开启不一定立即执行,由cpu调度决定*/public class MyThread extends Thread{@Overridepublic void run() {for (int i = 0; i < 10; i++) {System.out.println("我爱学习"+i);}}public static void main(String[] args) {//开启线程new MyThread().start();for (int i = 0; i < 1000; i++) {System.out.println("你不爱学习"+i);}}}
例子: 通过url下载图片
//下载网图
public class MyThreadTest extends Thread{private URL url; //图片地址private String name; //下载下来图片名称public MyThreadTest(URL url,String name) {this.url = url;this.name = name;}@Overridepublic void run() {try {new Download().down(url,name);System.out.println("下载的文件名为"+name);} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) throws Exception {URL url = new URL("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic23" +".nipic.com%2F20120730%2F8820441_171402261000_2.jpg&refer=http%3A%2F%2Fpic23." +"nipic.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg? sec=1633077226&t=374063ccb6acc22d274616a58a359dd0");new MyThreadTest(url,"1.jpg").start();new MyThreadTest(url,"2.jpg").start();new MyThreadTest(url,"3.jpg").start();}
}
//下载器
class Download{public void down(URL url, String name) throws IOException {//使用commons-io包提供的方法FileUtils.copyURLToFile(url,new File(name),5000,5000);}
}
实现Runable接口
/*** 多线程实现方式二: 1.实现Runnable接口* 2.重写run方法.编写线程执行体* 3.将对象传入Thread对象,调用start方法启动线程*/
public class MyRunnable implements Runnable{@Overridepublic void run() {for (int i = 0; i < 10; i++) {System.out.println("runnable实现"+i);}}public static void main(String[] args) {MyRunnable runnable = new MyRunnable();new Thread(runnable,"新开线程1").start();for (int i = 0; i < 100; i++) {System.out.println("main主线程"+i);}}
}
例子:龟兔赛跑
//龟兔赛跑
public class Race implements Runnable{//确定唯一胜利者,当有胜利者时,剩余线程不用执行public static String winner;@Overridepublic void run() {for (int i = 0; i <= 5; i++) {boolean b = gameOver(i);if (b){break;}if (Thread.currentThread().getName().equals("兔子") && i%10==0){try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(Thread.currentThread().getName()+"跑了-->"+i+"步");}}public boolean gameOver(int i){if (winner != null){return true;}if (i >= 5) {winner = Thread.currentThread().getName();System.out.println("胜利者是--->"+winner);return true;}return false;}public static void main(String[] args) {Race race = new Race();new Thread(race,"乌龟").start();new Thread(race,"兔子").start();}
}/*打印结果
乌龟跑了-->0步
乌龟跑了-->1步
乌龟跑了-->2步
乌龟跑了-->3步
乌龟跑了-->4步
胜利者是--->乌龟
兔子跑了-->0步
*/
为什么结尾还有一个兔子跑了-->0步?
==> 兔子线程在乌龟跑到5的时候就已经启动过,但是sleep了.因为判断是否已经gameOver在线程sleep上面执行---调换位置即可@Overridepublic void run() {for (int i = 0; i <= 5; i++) {if (Thread.currentThread().getName().equals("兔子") && i%10==0){try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}//胜利者是否诞生boolean b = gameOver(i);if (b){break;}System.out.println(Thread.currentThread().getName()+"跑了-->"+i+"步");}}
实现Callable接口
- 好处: 1. 可以定义返回值
- 可以抛出异常
/**多线程实现方式三: 1.实现Callable接口2.重写call方法,需要抛出异常3.创建目标对象4.创建执行服务5.提交执行6.获取结果7.关闭服务*/
public class ThreadTest implements Callable<Boolean> {@Overridepublic Boolean call() throws Exception {return true;}public static void main(String[] args) throws ExecutionException, InterruptedException {//创建目标对象ThreadTest threadTest = new ThreadTest();//创建执行服务ExecutorService service = Executors.newFixedThreadPool(1);//提交执行Future future = service.submit(threadTest);//获取结果boolean b = (boolean) future.get();System.out.println(b);//关闭服务service.shutdownNow();}
}
静态代理
/*静态代理:真实对象和代理对象实现同一个接口代理对象要代理真实角色好处:代理对象对真实对象进行功能升级真实对象专注做自己的事情
*/
public class StaticProxy {public static void main(String[] args) {/* You you = new You();WeddingCompany weddingCompany = new WeddingCompany(you);weddingCompany.happyMarry();*/new WeddingCompany(new You()).happyMarry();}
}interface Marry{void happyMarry();
}
//真实角色
class You implements Marry{@Overridepublic void happyMarry() {System.out.println("张某人快乐.结婚");}
}
//代理角色
class WeddingCompany implements Marry{private Marry targer;public WeddingCompany(Marry targer) {this.targer = targer;}@Overridepublic void happyMarry() {before();this.targer.happyMarry();after();}private void after() {System.out.println("婚礼结束,收尾款");}private void before() {System.out.println("婚礼之前,布置现场");}
}
Thread底层实现方式
比较:
new WeddingCompany(new You()).happyMarry(); //静态代理模式
new Thread(runnable,“新开线程1”).start(); //线程开启Runnable方式
Thread底层就是基于静态代理模式
Lamda表达式
- 想使用lamda表达式,接口必须满足函数式接口
- 函数式接口 —> 接口中只有一个抽象方法
- lamda表达式 —>简化代码
lamda进化过程
public class LambdaEvolve {//2.静态内部类方式static class Student2 implements Person{@Overridepublic void lambda() {System.out.println("学习lambda很快乐2");}}public static void main(String[] args) {Person student;//1.实现接口方式student = new Student();student.lambda();//2.静态内部类方式student = new Student2();student.lambda();//3.局部内部类方式class Student3 implements Person{@Overridepublic void lambda() {System.out.println("学习lambda很快乐3");}}student = new Student3();student.lambda();//4.匿名内部类方式student = new Person() {@Overridepublic void lambda() {System.out.println("学习lambda很快乐4");}};student.lambda();//5. lambda表达式方式student = ()->{System.out.println("学习lambda很快乐5");};student.lambda();}
}//定义函数式接口
interface Person{void lambda();
}//定义实体类实现
class Student implements Person{@Overridepublic void lambda() {System.out.println("学习lambda很快乐");}
}
lamda简化过程
public class LambdaSimoLify {//前提: 函数式接口public static void main(String[] args) {TestLamda testLamda;//普通版testLamda = (int a)->{System.out.println("你好"+a);};//简化1:参数类型 --->多个参数,参数类型去掉就都去掉testLamda = (a)->{System.out.println("你好"+a);};//简化2:简化括号 --->只有一个参数才行testLamda = a->{System.out.println("你好"+a);};//简化3: 去掉花括号 -->只有一行代码时才可以testLamda = a->System.out.println("你好"+a);testLamda.test(5);//综上: 推荐使用:testLamda = (a)->{System.out.println("你好"+a);};}
}
interface TestLamda{void test(int a);
}
线程操作
线程状态
线程状态观测
Thread.State
- NEW 尚未启动的线程处于此状态
- RUNNABLE 在JAVA虚拟机中执行的线程处于此状态
- BLOCKED 被阻塞等待监视器锁定的线程处于此状态
- WAITING 正在等待另一个线程执行特定动作的线程处于此状态
- TIMED_WAITING 正在等待另外一个线程执行动作达到指定等待时间的线程处于此状态
- TERMINATED 已退出的线程处于此状态
//线程状态
public class ThreadState {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(()->{try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"线程运行");});//观察状态NEWThread.State state = thread.getState();System.out.println(state);//观察启动后状态 RUNNABLEthread.start();state = thread.getState();System.out.println(state);while (state != Thread.State.TERMINATED){Thread.sleep(100);state = thread.getState();System.out.println(state);}}
}
线程停止
- 不推荐使用JDK提供的stop()、destory()方法 [已废弃] -->下面有说明
- 推荐线程自己停下来
- 使用标志位进行控制
public class TestStop implements Runnable{//使用标志位让线程停下来private boolean flag = true;@Overridepublic void run() {while (flag){System.out.println("thread is run....");}}//自定义stop方法public void stop(){this.flag = false;}public static void main(String[] args) {TestStop ts = new TestStop();new Thread(ts).start();for (int i = 0; i < 500; i++) {if (i == 400){ts.stop();System.out.println("线程停止");}System.out.println("main线程++"+i);}}
}
线程停止为什么不推荐使用stop()和distory()方法?
stop(): 此方法可以强行终止一个正在运行或挂起的线程。但stop方法不安全,就像强行切断计算机电源,而不是正常程序关机,可能会产生不可预料的结果
举例来说:
当一个线程对象上调用stop()方法时,这个线程对象所运行的线程就会立即停止,并抛出特殊的ThreadDeath()异常。这里的"立即"因为太"立即"了。
假如一个线程正在执行:synchronized void { x = 3; y = 4; }
由于方法时同步的,多个线程访问时总能保证想x,y被同时赋值,而如果一个线程正在执行到x=3时,被调用了 stop()方法,即使在同步块中,它也干脆地stop了,这样就产生了不完整的残废数据。而多线程编程中最最基础的条件要保证数据的完整性,所以请忘记 线程的stop方法,以后我们再也不要说“停止线程”了。
destroy():该方法最初用于破坏该线程,但不作任何资源释放。它所保持的任何监视器都会保持锁定状态。不过,该方法决不会被实现。即使要实现,它也极有可能以 suspend() 方式被死锁。如果目标线程被破坏时保持一个保护关键系统资源的锁,则任何线程在任何时候都无法再次访问该资源。如果另一个线程曾试图锁定该资源,则会出现死锁。
线程休眠_sleep
每一个对象都有一个锁,sleep不会释放锁
//网络延时:放大问题的发生性
public class TestSleep {public static void main(String[] args) throws InterruptedException {//模拟倒计时tenDown();//每隔一秒打印系统时间Date date = new Date();while(true){System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date));Thread.sleep(1000);date = new Date();}}public static void tenDown() throws InterruptedException {int num = 10;while(true){System.out.println(num--);Thread.sleep(1000);if (num <= 0){break;}}}
}
线程礼让_yield
//礼让不一定成功,看cpu心情
public class TestYield {public static void main(String[] args) {Runnable thread = ()->{System.out.println(Thread.currentThread().getName()+"-->开始执行");//礼让Thread.yield();System.out.println(Thread.currentThread().getName()+"-->结束执行");};new Thread(thread,"a").start();new Thread(thread,"b").start();}
}
线程强制执行_Join
/*** Join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞* 可以理解为 --->插队*/
public class TestJoin {public static void main(String[] args) throws InterruptedException {Runnable td = ()->{for (int i = 0; i < 10; i++) {System.out.println("vip线程来哦"+i);}};Thread thread = new Thread(td);thread.start();for (int i = 0; i < 20; i++) {if (i == 10){//线程强制执行thread.join();}System.out.println("main线程"+i);}}
}
线程优先级_priority
//设置线程优先级 默认5
public class ThreadPriority {public static void main(String[] args) {Runnable runnable = ()-> System.out.println(Thread.currentThread().getName()+"线程运行,优先级+"+Thread.currentThread().getPriority());//主线程mainSystem.out.println(Thread.currentThread().getName()+"线程运行,优先级+"+Thread.currentThread().getPriority());Thread thread = new Thread(runnable);Thread thread1 = new Thread(runnable);Thread thread2 = new Thread(runnable);Thread thread3 = new Thread(runnable);Thread thread4 = new Thread(runnable);thread.setPriority(Thread.MIN_PRIORITY);thread.start();thread1.setPriority(1);thread1.start();thread2.setPriority(2);thread2.start();thread3.setPriority(3);thread3.start();thread4.setPriority(Thread.MAX_PRIORITY);thread4.start();}
}
守护线程_deamon
- 线程分为 用户线程 和守护线程
- 虚拟机必须确保用户线程执行完毕
- 虚拟机不用等待守护线程执行完毕
- 如,后台记录操作,监控内存,垃圾回收等
//测试守护线程
public class ThreadDaemon {public static void main(String[] args) {God god = new God();You you = new You();//设置上帝为守护线程Thread thread = new Thread(god);thread.setDaemon(true); //默认是 false 表示用户线程.正常的线程都是用户线程thread.start();//启动younew Thread(you).start(); /*当you 线程输出 goodbye 结束线程时.god线程也会输出几句然后关闭 (虚拟机关闭需要时间)*/}
}
class God implements Runnable{@Overridepublic void run() {while (true){System.out.println("上帝与你同在.....");}}
}
class You implements Runnable{@Overridepublic void run() {for (int i = 0; i < 36500; i++) {System.out.println("你在世第.."+i+"天");}System.out.println("goodbye word!");}
}
线程同步
**并发:** ==同一个对象被多个线程同时操作==**线程同步:** 解决并发问题 ----> ==排队(队列) +锁==**锁机制Synchronized:** 线程获得对象锁,其他线程只能等待,等锁释放后在获取锁进入
问题: 1.性能变差2.有可能产生性能倒置问题
// 并发问题 模拟 ---->抢票 --->核心原因 线程都有自己的工作内存
// -->同时操作一个资源,都将资源带入自己的工作内存交互, 当票数为1时.两个线程都将1带入自己线程交互,结果出现了0
public class TestTicket implements Runnable {private int ticket = 10;@Overridepublic void run() {while(ticket >=1){try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"抢到第"+ticket-- + "张票");}}public static void main(String[] args) {TestTicket ticket = new TestTicket();Thread thread = new Thread(ticket, "a");Thread thread2 = new Thread(ticket, "b");thread.start();thread2.start();}
}
/*** a抢到第9张票* b抢到第10张票* a抢到第8张票* b抢到第7张票* a抢到第6张票* b抢到第6张票* b抢到第5张票* a抢到第4张票* a抢到第3张票* b抢到第2张票* a抢到第1张票* b抢到第0张票 可看出,当多个线程操作同一资源时,时不安全的*/
//ArrayList线程不安全
public class UnsafeThreadList {public static void main(String[] args) throws InterruptedException {List<String> list = new ArrayList<>();for (int i = 0; i < 10000; i++) {new Thread( ()-> list.add(Thread.currentThread().getName())).start();}Thread.sleep(5000);System.out.println(list.size()); //9998}
}
同步方法,同步代码块
synchronized默认锁是当前类对象------每个对象都对应一把锁
- 同步方法
public synchronized void method(int args){}
同步方法 限制–> 因为syncronized在方法上获取的锁是当前类的锁,当你对别的类中的数据作出改变,synchronized关键字没用
so —同步代码块出
- 同步代码块
synchronized (obj){} obj代表你需要增删改查的对象,让其线程同步.
//同步方法的使用
public class ThreadTest implements Runnable{private int ticket = 10;@Overridepublic synchronized void run() {while(ticket >=1){try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"抢到第"+ticket-- + "张票");}}//同步代码块的使用List<String> list = new ArrayList<>();for (int i = 0; i < 10000; i++) {synchronized (list){new Thread( ()-> list.add(Thread.currentThread().getName())).start();}}
死锁
- 多个线程互相抱着对方需要的资源,然后形成僵持
- 某一个同步块**同时拥有两个以上对象的锁**就有可能产生死锁
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 Lipstick lipstick = new Lipstick(); //保证锁对象的唯一性static Mirror mirror = new Mirror();private int choice;private String girlName;public Makeup(int choice, String girlName){this.choice = choice;this.girlName = girlName;}@Overridepublic 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锁
- lock是显示锁,synchronized是隐式锁
- 一般使用子类 ReentrantLock来 可重入锁
- Lock > 同步代码块 > 同步方法 (效率上来说)
public class TestLock {public static void main(String[] args) {TicketTest ticketTest = new TicketTest();new Thread(ticketTest).start();new Thread(ticketTest).start();new Thread(ticketTest).start();}
}class TicketTest implements Runnable{private int ticket = 10;private final Lock lock = new ReentrantLock();@Overridepublic void run() {try{lock.lock();//开启锁while (ticket > 0){System.out.println(ticket--);}}finally {lock.unlock(); //释放锁}}
}
线程通信
线程通信 ----> 生产者or消费者: 生产者–生产–> 东西 <–消费–消费者消费
线程通信: 这是一个线程问题,生产者和消费者共享同一资源,并且生产者和消费者之间相互依赖,互为条件
synchronized 可组织并发更新同一个共享资源,实现同步…却不能实现不同线程之间的信息传递(通信)
解决方法:
一: 管程法
生产者将生产好的数据放入 **缓冲区**, 消费者从**缓冲区**拿出数据
二: 信号灯法
给一个标志符 ,, 有消费者消费,无,消费者等待
- 线程通信方法
方法名 | 作用 |
---|---|
wait() | 表示线程一直等待,直到其他线程通知,与sleep不同,会释放锁 |
wait(Long timeout) | 指定等待的毫秒值 |
notify() | 唤醒一个处于等待状态的线程 |
notifyAll() | 唤醒同一个对象上所有调用wait()方法的线程,优先级高的线程优先调度 |
注意: 均是Object类的方法。都只能在同步方法或者同步代码块中使用,否则会抛出异常IllegalMonitorStateException
管程法
//线程通信,生产者和消费者 ---中间加入缓存区---->管程法
public class ThreadPC {public static void main(String[] args) {Buffer buffer = new Buffer();new Producer(buffer).start();new Customer(buffer).start();}
}//生产者
class Producer extends Thread{Buffer buffer;public Producer(Buffer buffer) {this.buffer = buffer;}//生产@Overridepublic void run() {for (int i = 0; i < 100; i++) {buffer.put(new Chicken(i));System.out.println("生产了第-->"+i+"只鸡");}}
}
//消费者
class Customer extends Thread{Buffer buffer;public Customer(Buffer buffer) {this.buffer = buffer;}@Overridepublic void run() {for (int i = 0; i < 100; i++) {Chicken chicken = buffer.get();System.out.println("消费了第-->"+chicken.id+"只鸡");}}
}//产品
class Chicken{int id;public Chicken(int id) {this.id = id;}
}//缓存区
class Buffer{//容器.装产品Chicken[] chickens = new Chicken[10];//计数int count = 0;//生产者生产产品丢入容器public synchronized void put(Chicken chicken){//判断容器中是否已满if (count == chickens.length){//容器满了.生产者等待try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}//生产者生产.添加chickens[count]=chicken;count++;//通知消费者消费this.notifyAll();}//消费者消费产品public synchronized Chicken get(){//消费者判断容器中是否有产品if (count == 0){//消费者等待try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}//消费Chicken chicken = chickens[count-1];chickens[count-1] = null;count--;//通知生产者生产this.notifyAll();return chicken;}
}
信号灯法
//测试信号灯方式 标志符
public class TestSignalLamp {public static void main(String[] args) {Exchange exchange = new Exchange();new Producer1(exchange).start();new Customer1(exchange).start();}
}//生产者
class Producer1 extends Thread{Exchange exchange;public Producer1(Exchange exchange) {this.exchange = exchange;}//生产鸡@Overridepublic void run() {for (int i = 0; i < 100; i++) {exchange.doChicken(new Chicken1(i));}}
}
//消费者
class Customer1 extends Thread{Exchange exchange;public Customer1(Exchange exchange) {this.exchange = exchange;}@Overridepublic void run() {for (int i = 0; i < 100; i++) {exchange.eatChicken();}}
}//产品
class Chicken1{int id;public Chicken1(int id) {this.id = id;}
}//标志符--通信
class Exchange{//定义标志符boolean flag;Chicken1 chicken;//生产者做鸡public synchronized void doChicken(Chicken1 ck){//当标志符为true时,生产线程等待if (flag){try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}this.chicken = ck;this.flag = true;System.out.println("生产了一只鸡"+chicken.id);//通知消费者this.notifyAll();}//消费者吃鸡public synchronized void eatChicken(){//当flag为false时无鸡可吃if (!flag){try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("吃了一只鸡==_=="+chicken.id);chicken = null;this.flag = false;//通知生产生产this.notifyAll();}
}
线程池
提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回池中。避免频繁创建与销毁、实现重复利用,提高效率
- 提高响应速度(减少了创建线程时间)
- 降低资源消耗(可重复使用)
- 便于管理
- corePoolSize: 核心池大小
- maximumPoolSize : 最大线程数
- keepAliveTime: 线程没有任务时最多保持多长时间会终止
public class TestPool {public static void main(String[] args) {//创建线程池--指定线程数ExecutorService service = Executors.newFixedThreadPool(10);//执行service.execute(new MyThread());service.execute(new MyThread());service.execute(new MyThread());service.execute(new MyThread());service.execute(new MyThread());//关闭链接service.shutdown();}
}class MyThread implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"创建滴滴滴");}
}
多线程-静态代理-Lambda表达式相关推荐
- 反射、Lambda表达式(Java学习笔记十二)
文章目录 反射 Class 类 创建运行时类的对象 获取运行时类的完整结构 调用运行时类的指定结构 调用指定方法 调用指定属性 关于setAccessible方法的使用: 动态代理 Lambda表达式 ...
- Java笔记 - 黑马程序员_08(Lambda表达式,接口组成更新,方法引用,类加载器,反射)
1. Lambda 1.1 函数式编程思想概述 在数学中,函数就是有输入量.输出量的一套计算方案,也就是"数据做操作" 面向对象思想强调"必须通过对象的形式来做事情&qu ...
- 接口(jdk1.8及之后) 单例模式(饿汉式,懒汉式) 静态代理模式 简单工厂模式 匿名内部类 lambda表达式
接口: jdk1.8及之后新增了2种可以定义存在方法体的方法: 默认方法 (default关键字修饰的方法 ) 使用:通过实现类对象使用 静态方法 (掌握) 使用:通过接口名去调用 目前接口中: 必须 ...
- 静态代理模式(多线程底部原理)
静态代理模式总结(线程底部原理) 真实对象和代理对象都要实现同一个接口 代理对象要代理真实角色 好处: - 代理对象可以做很多真实对象做不了的事情 - 真实对象专注做自己的事情 创建静态代理模式:一个 ...
- Java基础---学Java怎么能不了解多线程---Lambda表达式
多线程 程序,进程,线程 1.程序(program):一个固定的运行逻辑和数据的集合,是一个静态的概念,一般都存储在磁盘中 2.进程(process):一个正在运行的程序,是一个程序的一次运行,是一个 ...
- 五、Java中常用的API(通过包进行分类)————异常、多线程和Lambda表达式
之前已经介绍了java.lang包下的相关类,今天将要补充两个常用的API:java.lang.Throwable和java.lang.Thread 一.异常(java.lang.Throwable) ...
- Java学习记录五(多线程、网络编程、Lambda表达式和接口组成更新)
Java学习记录五(多线程.网络编程.Lambda表达式和接口组成更新) Java 25.多线程 25.1实现多线程 25.1.1进程 25.1.2线程 25.1.3多线程的实现 25.1.4设置和获 ...
- 多线程、线程池以及Lambda表达式的总结笔记分享
文章目录 1. 多线程技术 1.1 线程与进程 1.2 守护线程和用户线程 1.3 线程的六种状态 1.4 线程的调度 1.5 同步与异步 1.6 并发与并行 1.7 Thread类 1.7.1 Th ...
- C++多线程:Lambda表达式
定义 Lambda 表达式可以说是c++11引用的最重要的特性之一,虽然跟多线程关系不大,但是它在多线程的场景下使用很频繁,所以在多线程这个主题下介绍它更合适.Lambda 来源于函数式编程的概念,也 ...
最新文章
- BZOJ 2440: [中山市选2011]完全平方数 [容斥原理 莫比乌斯函数]
- ASP.NET MVC基于标注特性的Model验证:DataAnnotationsModelValidator
- dos删除文件与文件夹
- 邀请参加活动的邀请函_圣诞节点灯仪式活动邀请函制作
- Hadoop点滴-HDFS命令行接口
- Web定时器 - Timer
- Golang AES 加解密
- 卷积神经网络学习项目--Kaggle仙人掌识别--基于TensorFlow(未完成)
- 如何在WPS 2019中将图片背景设置为透明
- office2007安装找不到文件问题
- 常用fastboot命令
- 加州大学伯克利分校与KyberNetwork联合进行去中心化交易所研究
- (转)水经注谷歌地图的级别与对应比例尺及分辨率探究
- 使用74LS164和74LS165实现简单I/O扩展
- python 矩阵特征值_用python求矩阵特征值的方法?
- 透过率和反射率的关系_玻璃透过率、反射率和吸收率的关系.doc
- 用计算机despair,despair的用法总结大全
- 中兴C300主控升级到V2.1.0要谨慎,(针对ONU光猫生产企业)
- These modules have been removed from Maven structure: ‘xxx‘ Do you want them to be removed f
- 音悦台800多万MV视频抓取
热门文章
- 华硕天选2wifi不见了
- python数据分析的app_Python数据分析与数据可视化知到APP答案
- 配置oracle数据库容许远程连接(包括通过plsql进行远程连接)
- java毕设项目家乡旅游文化推广网站(附源码)
- hp服务器装Ubuntu8系统,Ubuntu 8.10下安装HP LaserJet 1018 USB Printer
- 黄颀:实例讲解GRE词汇学习方法
- mathtype安装以及office2016兼容问题
- leaflet动态热力图分析(leaflet篇.16)
- TensorFlow2 大幅提高模型准确率的神奇操作
- C语言: 数列第一项为2,此后各项均为它前一项的两倍再加三,计算该数列前10项之和;