P2: Java多线程全面详解

静态代理模式

代理模式是面向对象编程比较常见的设计模式
在这里插入图片描述
需要注意的有下面几点:

  1. 用户只关心接口功能,而不在乎谁提供了功能。上图中接口是 Subject。
  2. 接口真正实现者是上图的 RealSubject,但是它不与用户直接接触,而是通过代理。
  3. 代理就是上图中的 Proxy,由于它实现了 Subject 接口,所以它能够直接与用户接触。
  4. 用户调用 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());
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值