学习线程,我们先来了解了解什么是进程?什么是线程
进程:就是在操作系统中运行的程序
线程:就是进程的一个执行单元,或者一条执行路劲
比如:我们打开应用商店,这个应用商店就是一个进程,应用商店里面也可以同时下载很多应用,每个应用的下载就是线程
一个进程至少有一个线程,一个进程里面如果有多个线程,我们称这个进程为多线程进程
我们先来看看程序没有多线程是怎样运行的
现在有一个售票的窗口 Ticket ,里面有可以买票的功能, 模拟两个人进行购票
 public void buyTicket(String name) {
        for (int i = 0; i < 5; i++) {
            System.out.println(name + "购买动车票");
        }
    }
    public static void main(String[] args) {
        Ticket ticket = new Ticket();
        ticket.buyTicket("小明");
        System.out.println(".................");
        Ticket ticket2 = new Ticket();
        ticket2.buyTicket("小红");
    }
 

 我们发现程序是 按照 顺序执行的,相当于购票窗口只有一个,得等到小明完成才能购票
小明买完票了,程序出错了,后面的人就不要买票了,恭喜小明包了一辆动车,这显然是不合理的,因此就需要多个窗口进行售票,这就是多线程的使用
线程的创建
在java中,应该怎么创建线程呢?
1. 继承Tread类,重写Run方法
public class Ticket extends Thread {
    private String name;
    @Override
    public void run() {
        Thread.currentThread().setName(name+"的线程");
        for (int i = 0; i < 300; i++) {
            System.out.println(Thread.currentThread().getName()+ "  购买动车票");
        }
    }
    public static void main(String[] args) {
        //创建线程1
        Ticket ticket = new Ticket();
        //创建线程2
        Ticket ticket2 = new Ticket();
        ticket2.name="小红";
        ticket.name="小明";
        //开始线程
        ticket.start();
        ticket2.start();
    }
}
 
2.实现runable接口
public class Ticket implements Runnable {
    private String name;
    @Override
    public void run() {
        for (int i = 0; i < 300; i++) {
            System.out.println(Thread.currentThread().getName() + "  " + name + "购买动车票");
        }
    }
    public static void main(String[] args) {
       //创建线程1
        Ticket ticket = new Ticket();
        ticket.name = "小明";
        Thread thread = new Thread(ticket);
         //开启线程 thread
        thread.start();
        ticket.name = "小红";
        Thread thread2 = new Thread(ticket);
        //开启线程 thread2
        thread2.start();
    }
}
 
3.实现Callable接口,使用FutureTask
public class Ticket implements Callable<Object> {
    private String name;
    @Override
    public Object call() throws Exception {
        for (int i = 0; i < 300; i++) {
            System.out.println(Thread.currentThread().getName() + "  " + name + "购买动车票");
        }
        return null;
    }
    public static void main(String[] args) {
    //创建线程1
        Ticket ticket = new Ticket();
        ticket.name = "小明";
        FutureTask<Object> task = new FutureTask<>(ticket);
    //开启线程 thread
        Thread thread = new Thread(task);
        thread.start();
    //创建线程2
        ticket.name = "小红";
        FutureTask<Object> task2 = new FutureTask<>(ticket);
        Thread thread2 = new Thread(task2);
    //开启线程 thread2
        thread2.start();
    }
}
 
三种创建线程的结果是一样的
输出结果:

 这里可以看出线程是在同时进行的,谁优先抢到CPU执行权谁先执行
面试必问:
创建线程有三种方式:
继承Thread类,重写run方法
 实现Runnnable接口,重写run方法
 实现Callable接口,重写 call 方法,使用FutureTask
这三种有什么差别呢?开发中应该使用什么方式
开发中建议使用 实现接口的方式创建 实现 Runnable(不可抛出异常) 实现 Callable (可以抛出异常)
我们都知道类可以多实现,只能单一继承,如果使用继承thread来创建线程,大大增加了局限性
其次,继承Thread方式创建多线程,也浪费了资源,几个线程就创建了几个对象,而其他两个只创建一个公享就行

 
 
线程的优先级
线程的执行,也是有优先级的,优先级较高的 更优于 优先级较低 ,也就是说,优先级更高更容易抢占到CPU执行
注意:只是概率更高,并不是一定优先执行
我们可以去设置线程的优先级
MAX_PRIORITY 最大优先级 取值10
 MiN_PRIORITY 最小优先级 取值1
 NORM_PRIORITY 默认优先级 取值 5
我们还可以通过
getPriority() 方法获取线程的优先级
 setPriority() 方法改变线程的优先级
public class Ticket implements Runnable {
    private String name;
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
//            System.out.println(Thread.currentThread().getName() + "  " + name + "购买动车票");
        }
    }
    public static void main(String[] args) {
        //创建线程1
        Ticket ticket = new Ticket();
        ticket.name = "小明";
        Thread thread = new Thread(ticket);
        //开启线程 thread
        thread.start();
        ticket.name = "小红";
        Thread thread2 = new Thread(ticket);
        //开启线程 thread2
        thread2.start();
        //获取线程优先级
        System.out.println(thread.getPriority());
        System.out.println(thread2.getPriority());
    }
}
 

 可以看到未设置优先级之前,默认为5
现在我们给小明的线程设置优先级为10
public class Ticket implements Runnable {
    private String name;
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
//            System.out.println(Thread.currentThread().getName() + "  " + name + "购买动车票");
        }
    }
    public static void main(String[] args) {
        //创建线程1
        Ticket ticket = new Ticket();
        ticket.name = "小明";
        Thread thread = new Thread(ticket);
        //设置优先级  最大  10 
        thread.setPriority(Thread.MAX_PRIORITY);
        //开启线程 thread
        thread.start();
        ticket.name = "小红";
        Thread thread2 = new Thread(ticket);
        //开启线程 thread2
        thread2.start();
        //获取线程优先级
        System.out.println(thread.getPriority());
        System.out.println(thread2.getPriority());
    }
}
 

 
 SpringBoot项目统一结果,统一异常,同一日志
面试官:说说 springboot 自动配置原理?
SpringBoot 中的自带工具类,开发效率增加一倍



















