Java多线程01

Process 与 Thread

进程 : 执行程序的一次过程, 是一个动态的概念. 是系统资源分配的单位

线程 : 一个进程中可以包含若干个线程. 是CPU调度和执行的最小单位

核心概念

  • 线程就是独立的执行路径
  • 在程序运行时, 即使自己没有创建线程, 后台也会有多个线程, 如主线程和 gc 线程等
  • main() 称之为主线程, 是系统的入口, 用于执行整个程序
  • 在一个进程中, 如果开辟了多线程, 线程的运行由调度器安排调度, 调度器是与操作系统紧密相关的, 先后顺序不受人为干预
  • 对同一份资源操作时, 会存在资源抢夺问题, 需要加入并发控制
  • 线程会带来额外的开销, 如CPU调度时间, 并发控制开销
  • 每个线程在自己的工作内存交互, 内存控制不当会造成数据不一致

线程创建

  • Thread class : 继承 Thread 类
  • Runnable 接口 : 实现 Runnable 接口
  • Callable 接口 : 实现 Callable 接口

调用 run 方法和 start 方法的区别

调用 start 方法才能实现多线程效果!

继承Thread类

package com.guanxing.lesson01;

//创建线程方式一:继承Thread类, 重写run()方法, 调用start开启线程
//总结:注意! 线程开启不一定立即执行, 由cpu调度

public class TestThread extends Thread{
    @Override
    public void run() {
        //run方法线程体
        for (int i = 0; i < 20; i++) {
            System.out.println("我在看代码---" + i);
        }
    }

    public static void main(String[] args) {
        //main线程, 主线程
        //创建一个线程对象, 调用start方法开启线程
        TestThread testThread1 = new TestThread();
//        testThread1.run();
        testThread1.start();
        for (int i = 0; i < 20; i++) {
            System.out.println("我在学习多线程---" + i);
        }
    }
}

实现Runable接口

package com.guanxing.lesson01;

//创建线程方式二:实现runnable接口,重写run方法,执行线程需要丢入runnable接口实现类,调用start方法

public class TestThread2 implements Runnable{
    @Override
    public void run() {
        //run方法线程体
        for (int i = 0; i < 500; i++) {
            System.out.println("我在看代码-----"+i);
        }
    }

    public static void main(String[] args) {
        //创建runnable接口的实现类对象
        TestThread2 testThread2 = new TestThread2();

        //创建线程对象,通过线程对象来开启我们的线程(代理)
//        Thread thread = new Thread(testThread2);
//        thread.start();
        new Thread(testThread2).start();

        for (int i = 0; i < 1000; i++) {
            System.out.println("我在学习多线程-----"+i);
        }
    }
}

小结

  • 继承Thread类
    • 启动线程:子类对象.start()
  • 实现Runnable接口
    • 启动线程:传入目标对象+Thread对象.start()
    • 推荐使用!
TestThread testThread1 = new TestThread();
	testThread1.start();

TestThread2 testThread2 = new TestThread2();
	Thread thread = new Thread(testThread2);
	thread.start();

静态代理模式

package com.guanxing.StaticProxy;
//静态代理模式总结:真实对象和代理对象都要代理同一个接口!
//代理对象要代理真实角色

//好处:
    //代理对象可以做很多真实对象做不了的事情
    //真实对象专注做自己的事情
public class StaticProxy {
    public static void main(String[] args) {
        //实例化用户jay
        User jay = new User();
        //将用户jay丢给婚庆公司
        WeddingCompany weddingCompany = new WeddingCompany(jay);
        weddingCompany.HappyMarry();

        //静态代理和线程的类比
        // new 代理类( 真实对象 ).执行方法;
        new Thread( ()-> System.out.println("我爱你") ).start();
        new WeddingCompany(new User()).HappyMarry();
    }
}

//实现一个结婚接口
interface Marry {
    void HappyMarry();
}

//定义一个用户类
//真实对象
class User implements Marry {
    @Override
    public void HappyMarry() {
        System.out.println("我要结婚了,超开心!");
    }
}

//定义婚庆公司类
//代理角色,代理用户去结婚
class WeddingCompany implements Marry {
    //要代理的真实角色
    private Marry target;

    public WeddingCompany(Marry target) {
        this.target = target;
    }

    @Override
    public void HappyMarry() {
        before();
        target.HappyMarry();
        after();
    }

    private void before() {
        System.out.println("婚礼之前,布置现场");
    }

    private void after() {
        System.out.println("婚礼之后,收尾款...");
    }
}

Lambda表达式

函数式接口:

  • 只包含唯一一个抽象方法的任意接口
  • 对于函数式接口,我们可以通过lambda表达式来创建该接口的对象
public interface Runnable {
    public abstract void run();
}

演变推导

package com.guanxing.lambda;

/*
推导lambda表达式
 */
public class TestLambda01 {
    //3.静态内部类
    static class Like2 implements ILike {
        @Override
        public void lambda() {
            System.out.println("i like lambda2");
        }
    }

    public static void main(String[] args) {
        ILike like = new Like();
        like.lambda();

        like = new Like2();
        like.lambda();

        //4.局部内部类
        class Like3 implements ILike {
            @Override
            public void lambda() {
                System.out.println("i like lambda3");
            }
        }
        like = new Like3();
        like.lambda();

        //5.匿名内部类(没有类的名称,必须借助接口或父类)
        like = new ILike() {
            @Override
            public void lambda() {
                System.out.println("i like lambda4");
            }
        };
        like.lambda();

        //6.用lambda简化
        like = () -> {
            System.out.println("i like lambda5");
        };
        like.lambda();
    }
}

//1.定义一个函数式接口
interface ILike {
    void lambda();
}

//2.实现类
class Like implements ILike {
    @Override
    public void lambda() {
        System.out.println("i like lambda");
    }
}
package com.guanxing.lambda;

public class TestLambda02 {
    public static void main(String[] args) {
//        ILove love = (int a) -> {
//            System.out.println("i love you--->"+a);
//        };
//        love.love(520);
        
        //终极简化版
        ILove love = null;
        love = a -> System.out.println("i love you--->"+a);
        love.love(520);
        
        //总结:
            //lambda表达式在只有一行代码的情况下才能去掉花括号!
            //前提是接口为函数式接口
            //多个参数也可以去掉参数类型,要去掉就都去掉,必须加上括号 
    }
}

//定义函数时接口
interface ILove {
    void love(int a);
}

优点:

  • 避免匿名内部类定义过多
  • 简化代码,只留下核心逻辑
原文地址:https://www.cnblogs.com/straightup/p/14503469.html