学习java的第三十九天,Callable多线程接口、静态代理、lambda表达式、线程状态、线程停止、线程休眠、线程强制执行的基础认知

一、Callable多线程接口

  1. 实现Callable接口,需要返回值类型
  2. 重写call方法,需要抛出异常
  3. 创建目标对象
  4. 创建执行服务:ExecutorService ser = Executors.newFixedThreadPool(线程数量:1);
  5. 提交执行:Futura r1 = ser.submit(t1);
  6. 获取结果:boolean rs1 = result.get();
  7. 关闭服务:ser.shutdownNow();
  • 创建测试类,依然是下载图片的例子,大致方法并没有改变,主要是调用线程输出的方法。
package com.Thread.CallableThread;
//下载网络图片,使用calleble接口实现

import com.Thread.threadall.TestThread2;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.*;

public class TestCalleble implements Callable {
    private String url;
    private String name;
    //有参构造器
    public TestCalleble(String url,String name){
        this.url = url;
        this.name = name;
    }



    @Override
    //重写call方法
    public Object call() throws Exception {
        Downlaod downlaod = new Downlaod();
        downlaod.downlaoder(url,name);
        System.out.println("下载了:"+name);
        return true;
    }
    //主程序入口
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        TestCalleble t1 = new TestCalleble("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fc-ssl.duitang.com%2Fuploads%2Fblog%2F202107%2F09%2F20210709142454_dc8dc.thumb.1000_0.jpeg&refer=http%3A%2F%2Fc-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1660501917&t=31c14fd02ce38e35be2a4cab0ec74a7b", "F:/1.jpg");
        TestCalleble t2 = new TestCalleble("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fc-ssl.duitang.com%2Fuploads%2Fitem%2F202009%2F23%2F20200923185609_rQUdj.thumb.1000_0.jpeg&refer=http%3A%2F%2Fc-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1660554163&t=8e75dd104b9c2c649b5b2d6421a3ffc6", "F:/2.jpg");
        TestCalleble t3 = new TestCalleble("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fup.enterdesk.com%2Fedpic_source%2F91%2F81%2Fd7%2F9181d7d8787f7e96f0017da5e61ad27d.jpg&refer=http%3A%2F%2Fup.enterdesk.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1660554163&t=85a991ac7c4dfb61dd44008a14e9a8c6", "F:/3.jpg");

        //创建执行服务
        ExecutorService ser = Executors.newFixedThreadPool(3);  //线程池
        //提交执行服务
        Future<Boolean> r1 = ser.submit(t1);
        Future<Boolean> r2 = ser.submit(t2);
        Future<Boolean> r3 = ser.submit(t3);

        //获取结果
        boolean rs1 = r1.get();
        boolean rs2 = r2.get();
        boolean rs3 = r3.get();
        System.out.println(rs1);
        System.out.println(rs2);
        System.out.println(rs3);

        //关闭服务
        ser.shutdownNow();


    }
}
//创建下载器类
class Downlaod{
    //实现下载器的方法
    public void downlaoder(String url,String name){
        try {
            FileUtils.copyURLToFile(new URL(url),new File(name));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

  • 结果图

在这里插入图片描述

二、静态代理

简单例子:
  • 你:真实角色
  • 婚庆公司:代理你,帮你处理结婚的事
  • 结婚:实现结婚接口即可
package com.Thread.StaticProxy;


//静态代理,模拟结婚代理

//静态代理模式总结:
//1.真实对象和代理对象都要实现同一个接口
//2.真实对象专注做自己的事情

//好处:
    //代理对象可以做很多真实对象做不了的事情!
    //真实对象专注做自己的事情!

public class Staticproxy {
    //主线程
    public static void main(String[] args) {
        //调用代理对象,代理对象中需要传递一个需要代理的值,而这个值需要实现Marry接口
        WedingCompany wedingCompany = new WedingCompany(new You());
        wedingCompany.HappyMarry();
    }
}
//接口,用来规范一件事情,比如目前是结婚
interface Marry{
   void HappyMarry();  //这个是方法
}

//真实对象,被代理的对象
class You implements Marry{

    @Override
    public void HappyMarry() {
        //只需要开心就可以了。其他事情交给代理去做
        System.out.println("要结婚啦!超开心");
    }
}

//代理对象
class WedingCompany implements Marry{
    //创建一个需要代理的对象,而这个对象需要实现Marry接口
    private Marry ta;
    //有参构造器,将值传到构造器中,方便调用
    public WedingCompany(Marry ta) {
        this.ta = ta;
    }

    @Override
    public void HappyMarry() {
        //实现结婚前,代理对象需要做的方法
        qian();
        //实现真实对象的方法,该对象必须调用HappyMarry
        this.ta.HappyMarry();
        //实现结婚后,代理对象需要做的方法
        hou();
    }
    
    private void hou() {
        System.out.println("结婚后,收尾款");
    }

    private void qian() {
        System.out.println("结婚前,布置场地");
    }
}


  • 结果图

在这里插入图片描述

静态代理模式总结:
1.真实对象和代理对象都要实现同一个接口
2.真实对象专注做自己的事情
好处:
1. 代理对象可以做很多真实对象做不了的事情!
2. 真实对象专注做自己的事情!

三、Lambda表达式

  • 为什么要使用lambda表达式?
  1. 避免匿名内部类定义过多
  2. 可以让代码看起来很简洁
  3. 去掉了一堆没有意义的代码,只留下核心的逻辑
  • 使用代码测试:
package com.Thread.Lambda;
//测试Lambda表达式
public class TestLambda {
    //静态内部类
    static class Love2 implements Ilove{

        @Override
        public void love(int a) {
            System.out.println("我爱你-->"+a);
        }
    }

    public static void main(String[] args) {

        //局部内部类
        class Love3 implements Ilove{

            @Override
            public void love(int a) {
                System.out.println("我爱你-->"+a);
            }
        }


        Ilove love = new Love1();
        love.love(1);

        Ilove love2 = new Love2();
        love2.love(2);

        Ilove love3 = new Love3();
        love3.love(3);
        //匿名内部类
        Ilove ilove = new Ilove() {
            @Override
            public void love(int a) {
                System.out.println("我爱你-->"+a);
            }
        };
        ilove.love(4);
        //1.Lambda表达式简化
        Ilove ilove1 = (int a)-> {
            System.out.println("Lambda表达式-->"+a);
            };
        ilove1.love(520);

        //简化1  去掉类型
        ilove1 =(a) ->{
            System.out.println("Lambda表达式简化1---"+a);
        };
        ilove1.love(1);
        //简化2  去掉括号
        ilove1 = a -> {
            System.out.println("Lambda表达式简化2---"+a);
        };
        ilove1.love(2);

        //简化3  去掉花括号
        ilove1 = a -> System.out.println("Lambda表达式简化3---"+a);
        ilove1.love(3);

    }


}


interface Ilove{
    void love(int a);
}
//内部类
class Love1 implements  Ilove{
    @Override
    public void love(int a) {
        System.out.println("我爱你-->"+a);
    }
}

结果图:

在这里插入图片描述


四、线程状态

线程中有以下五个状态

新生状态 – > 就绪状态 --> 运行状态 --> 阻塞状态 --> 死亡状态(结束状态)
  • 新生状态:Thread t = new Thread() 线程对象一旦创建就进入到了新生状态
  • 就绪状态:当线程调用了start方法,线程立即进入就绪状态,但不意味着立即调度执行
  • 运行状态:进入运行状态,线程才真正执行线程体的代码块
  • 阻塞状态:当调用sleep,wait或同步锁定时,线程进入阻塞状态,就是代码不往下执行,阻塞时间解除后,重新进入就绪状态,等待cpu调度执行!
  • 结束状态:线程中断或者结束,一旦进入死亡状态,就不能再次启动!

五、线程停止stop

  • 不推荐使用JDK提供的stop()、destroy()方法。(已废弃)

  • 推荐线程自己停止下来。

  • 建议使用一个标志位进行终止变量,当flag=false,则终止线程运行。

  • 代码创建

package com.Thread.state;
//测试线程停止
public class TestStop implements Runnable{

  private   boolean flag = true;


    @Override
    public void run() {
        //创建布尔值,用来终止线程
        int i = 0;
        while (flag){
            System.out.println("run...Thread"+i++);
        }
    }
    public void stop1(){

        this.flag = false;
    }

    public static void main(String[] args) {
        TestStop testStop = new TestStop();
        new Thread(testStop).start();
        for (int i = 0; i < 1000; i++) {
            System.out.println("mani"+i);
            if (i==900){
                //调用stop方法切换标志位,让线程停止!
                testStop.stop1();
                System.out.println("线程停止啦!--------------------------");
            }

        }

    }

}


结果图

在这里插入图片描述

六、线程休眠sleep

  • sleep(时间)指定当前线程阻塞的毫秒数;
  • sleep存在异常InterruptedException;
  • sleep时间达到后线程进入就绪状态;
  • sleep可以模拟网络延时,倒计时等;
  • 每一个对象都有一把锁,sleep不会释放死锁;

创建代码测试

package com.Thread.state;
//模拟倒计时

import java.text.SimpleDateFormat;
import java.util.Date;

public class TestSleep2{

    public static void main(String[] args) throws InterruptedException {
        //打印当前系统时间
        Date startTime = new Date(System.currentTimeMillis());
        while (true) {
            Thread.sleep(1000);
            System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(startTime));
            startTime = new Date(System.currentTimeMillis());  //更新当前时间
        }

    }
    //模拟倒计时
    public static void tenDown() throws InterruptedException {
        int num = 10;
        while (true){
            Thread.sleep(1000);
            System.out.println("倒计时:"+num--);
            if (num<=0){
                break;
            }
        }
    }


}


结果图

在这里插入图片描述

七、线程礼让Yield

  • 礼让线程,让当前执行的线程暂停,但不阻塞
  • 将线程从运行状态转为就绪状态
  • 让cpu重新调度,礼让不一定成功!看cpu心情!
package com.Thread.state;

//测试线程礼让
//礼让不一定成功,看cpu心情
public class TestYield {
    public static void main(String[] args) {

        MyYield myYield = new MyYield();


        new Thread(myYield,"小孩").start();
        new Thread(myYield,"老人").start();
    }

}

class MyYield implements Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"线程开始执行");
        Thread.yield();
        System.out.println(Thread.currentThread().getName()+"线程停止执行");
    }
}

结果图:

在这里插入图片描述

八、线程强制执行-join

  • Join合并线程,待此线程执行完成后,再执行其他线程,其他线路阻塞!
  • 在使用Join前,依然会交互执行!
  • 可以想象成插队!
package com.Thread.state;


//测试Join方法  //想象插队

public class TestJoin implements Runnable{
    public static void main(String[] args) throws InterruptedException {
        //启动线程
        TestJoin testJoin = new TestJoin();
        Thread thread = new Thread(testJoin);  //代理启动
        thread.start();  //线程开始启动
        //主线程
        for (int i = 0; i < 500; i++) {
            if (i==200){
                thread.join();  //插队
            }
            System.out.println("main"+i);
        }

    }

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println("VIP线程来了!"+i);
        }
    }
}


结果图

在这里插入图片描述


注:文章仅做个人学习日记,不做学习建议,学习来源:狂神说

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值