静态代理模式
代理模式是面向对象编程比较常见的设计模式
需要注意的有下面几点:
- 用户只关心接口功能,而不在乎谁提供了功能。上图中接口是 Subject。
- 接口真正实现者是上图的 RealSubject,但是它不与用户直接接触,而是通过代理。
- 代理就是上图中的 Proxy,由于它实现了 Subject 接口,所以它能够直接与用户接触。
- 用户调用 Proxy 的时候,Proxy 内部调用了 RealSubject。所以,Proxy 是中介者,它可以增强 RealSubject 操作。
[静态代理实例]
package com.TestThread;
import com.snake.Data;
import java.text.SimpleDateFormat;
import java.util.Date;
//计算add()的运行时间
public class StaticProxy {
public static void main(String[] args) {
//使用代理者和被代理者来完成任务
User user = new User(); //被代理对象
UserProxy userProxy = new UserProxy(user); //代理对象
userProxy.add();
}
}
//声明接口
interface FeatureDao{
public abstract void add();
}
//User被代理类
class User implements FeatureDao{
@Override
public void add() {
System.out.println("执行核心逻辑....");
}
}
//代理类
class UserProxy implements FeatureDao{
private User targrt;
public UserProxy(User targrt){
this.targrt = targrt;
}
@Override
public void add() {
System.out.println("add方法开始执行....");
//计算某任务! 耗费的时间:毫秒
long startTime = System.currentTimeMillis();
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
long endTime = System.currentTimeMillis();
System.out.println("for循环耗时:"+(endTime-startTime)+"ms");
//获取当前的系统时间
SimpleDateFormat df = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
System.out.println(df.format(new Date())); //时间的输出
System.out.println("add方法结束执行....");
}
}
静态代理类优缺点
-
优点
使得真实角色处理的业务更加纯粹,不再去关注一些公共的事情。
公共的业务由代理来完成—实现业务的分工。
公共业务发生扩展时变得更加集中和方便。 -
缺点
类多了–多了代理类。工作量变大了。开发效率降低了。
Lambda表达式
-
Lambda 表达式是 JDK8 的一个新特性,可以取代大部分的匿名内部类,写出更优雅的 Java 代码,尤其在集合的遍历和其他集合操作中,可以极大地优化代码结构。
-
JDK 也提供了大量的内置函数式接口供我们使用,使得 Lambda 表达式的运用更加方便、高效。
对接口的要求
虽然使用 Lambda 表达式可以对某些接口进行简单的实现,但并不是所有的接口都可以使用 Lambda 表达式来实现。Lambda 规定接口中只能有一个需要被实现的方法,不是规定接口中只能有一个方法
jdk 8 中有另一个新特性:default, 被 default 修饰的方法会有默认实现,不是必须被实现的方法,所以不影响 Lambda 表达式的使用。
@FunctionalInterface
修饰函数式接口的,要求接口中的抽象方法只有一个。 这个注解往往会和 lambda 表达式一起出现。
无参逐步简化Lambda表达式实例
package com.TestThread;
public class LambdaDemo1 {
//3.静态内部类
static class Like2 implements Ilike{
@Override
public void lambda() {
System.out.println("I like Lambda-->2 ");
}
}
public static void main(String[] args) {
Like like = new Like();
like.lambda();
Like2 like2 = new Like2();
like2.lambda();
//4.局部内部类
class Like3 implements Ilike{
@Override
public void lambda() {
System.out.println("I like Lambda-->3");
}
}
Like3 like3 = new Like3();
like3.lambda();
//5.匿名内部类,没有类的名称,必须借助接口或者父类
Ilike like4 = new Ilike(){
@Override
public void lambda() {
System.out.println("I like Lambda-->4");
}
};
like4.lambda();
//6.用Lambda简化
like4 = ()-> System.out.println("I like Lambda-->5");
like4.lambda();
}
}
//1.定义一个函数式接口
@FunctionalInterface
interface Ilike{
void lambda();
}
//2.实现类
class Like implements Ilike{
@Override
public void lambda() {
System.out.println("I like Lambda-->1");
}
}
有参最简Lambda表达式实例
package com.TestThread;
//最简Lambda表达式
/*
* Lambda表达式只能有一行代码的情况下才能简化为一行
* 前提是接口为函数接口
* 多个参数时可以去掉参数类型,必须一致并且加括号
* */
public class LamdaDemo2 {
public static void main(String[] args) {
Ilove love = null ;
love = (a,b)-> System.out.println("I love you-->"+a+"&"+b);
love.love(520,502);
}
}
//定义一个有参函数接口
@FunctionalInterface
interface Ilove{
void love(int a,int b);
}
线程停止_stop
五大状态
- 不推荐使用JDK提供的stop(),destroy()方法.[已废弃]
- 推荐线程自己正常停止下来
- 建议使用一个标志位进行终止变量
当flag = Flase,则终止线程运行
[停止线程Stop实例]
package com.TestThread;
//测试Stop
public class StopDemo implements Runnable {
//设置一个标识符
private boolean flag = true;
//重写run()方法
@Override
public void run() {
int i = 0;
while (flag) {
System.out.println("run...Thread" + i++);
}
}
//创建一个公开的方法停止线程
public void stop(){
this.flag = false;
}
public static void main(String[] args) {
StopDemo stopDemo = new StopDemo();
new Thread(stopDemo).start();
for (int i = 0; i < 1200; i++) {
System.out.println("main" + i);
if (i == 1000){
//调用stop方法切换标识符,让线程停止
stopDemo.stop();
System.out.println("线程该停止啦!");
}
}
}
}
线程休眠_Sleep
- Sleep(时间)指定当前线程阻塞的毫秒数;
- Sleep存在异常InteruptedException;
- Sleep时间到达后线程进入就绪状态;
- Sleep可以模拟网络延时,倒计时;
- 每一个对象都有一把锁,Sleep不会释放锁;
[代码实例]
package com.TestThread;
import java.text.SimpleDateFormat;
import java.util.Date;
//模拟倒计时
public class SleepDemo {
public static void main(String[] args) {
//打印当前系统时间
Date startTime = new Date(System.currentTimeMillis());//获取系统当前时间
while (true){
try {
Thread.sleep(1000); //延时1000msc=1s
System.out.println(new SimpleDateFormat("HH;mm;ss").format(startTime));
startTime = new Date(System.currentTimeMillis());//更新当前系统时间
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/* 十秒倒计时
public static void main(String[] args) throws InterruptedException {
SleepDemo sleepDemo = new SleepDemo();
sleepDemo.tenDown();
}
public void tenDown() throws InterruptedException {
int num = 10;
while (true){
Thread.sleep(1000); //1000ms = 1s
System.out.println(num--);
if (num<=0){
break;
}
}
}*/
}
线程礼让_Yield
- 礼让线程,让当前正在执行的线程暂停,但不会导致线程转到等待/睡眠/阻塞状态;
- 将线程从运行状态转为就绪状态;
- 让CPU重新调度,但礼让不一定成功;
可能出现以下两种结果:
线程礼让代码实例
package com.TestThread;
//线程礼让
public class YieldDemo {
public static void main(String[] args) {
MyYield yield = new MyYield();
new Thread(yield,"a").start();
new Thread(yield,"b").start();
}
}
class MyYield implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程开始执行");
Thread.yield();
System.out.println(Thread.currentThread().getName()+"线程结束执行");
}
}
线程合并_ join
- 一个线程A在占有cpu资源期间,可以让其他资源调用join()和本线程联合;
当A在运行期间联合了B,A线程立即中断执行,一直等到他联合的B线程执行完毕,A线程再重新排队等待CPU资源。
线程合并代码实例
package com.TestThread;
//线程合并---join
public class JoinDemo implements Runnable{
public static void main(String[] args) {
//启动线程
JoinDemo joinDemo = new JoinDemo();
Thread thread = new Thread(joinDemo);
thread.start();
//主线程
for (int i = 0; i < 10; i++) {
System.out.println("main"+i);
if (i == 3){
try {
thread.join(); //插队
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("VIP线程来了"+i);
}
}
}
线程优先级_Priority
java 中的线程优先级的范围是1~10,默认的优先级是5。10极最高。
有时间片轮循机制。“高优先级线程”被分配CPU的概率高于“低优先级线程”。根据时间片轮循调度,所以能够并发执行。无论是是级别相同还是不同,线程调用都不会绝对按照优先级执行,每次执行结果都不一样,调度算法无规律可循,所以线程之间不能有先后依赖关系。
无时间片轮循机制时,高级别的线程优先执行,如果低级别的线程正在运行时,有高级别线程可运行状态,则会执行完低级别线程,再去执行高级别线程。如果低级别线程处于等待、睡眠、阻塞状态,或者调用yield()函数让当前运行线程回到可运行状态,以允许具有相同优先级或者高级别的其他线程获得运行机会。因此,使用yield()的目的是让相同优先级的线程之间能适当的轮转执行。但是,实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。结论:yield()从未导致线程转到等待/睡眠/阻塞状态。在大多数情况下,yield()将导致线程从运行状态转到可运行状态,但有可能没有效果。
[线程优先级代码实例]
package com.TestThread;
//测试线程的优先级
public class PriorityDemo {
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);
Thread t5 = new Thread(myPriority);
//先设置优先级在启动
t1.start();
t2.setPriority(1);
t2.start();
t3.setPriority(3);
t3.start();
t4.setPriority(Thread.MAX_PRIORITY);//MAX_PRIORITY = 10;
t4.start();
t5.setPriority(8);
t5.start();
}
}
class MyPriority implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
}
}