Java学习-7

线程

线程的调度:

    分时调度:所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间。
    抢占式调度:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性) , Java使用的为抢占式调度。

创建多线程的方式:

方法一:创建Thread类的子类

1.创建一个Thread类的子类
2.在Thread类的子类中重写Thread类中的run方法,设置线程任务(开启线程要做什么?)
3.创建Thread类的子类对象
4.调用Thread类中的方法start方法,开启新的线程,执行run方法

注意:void start()使该线程开始执行; Java虚拟机调用该线程的run方法。
结果是两个线程并发地运行;当前线程(main线程)和另一个线程(创建的新线程,执行其run 方法)。
多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。
java程序属于抢占式调度,那个线程的优先级高,那个线程优先执行;同个优先级,随机选择一个执行。

例:

Thread类的常用方法_获取线程名称

1.使用Thread类中的方法getName()
String getName() 返回该线程的名称。

2.可以先获取到当前正在执行的线程,使用线程中的方法getName( )获取线程的名称
static Thread currentThread() 返回对当前正在执行的线程对象的引用。

Thread类的常用方法_设置线程名称

Thread类的常用方法_sleep方法
让程序暂停多少毫秒,例:

方法二:实现Runnable接口

1.创建一个Runnable接口的实现类
2.在实现类中重写Runnable接口的run方法,设置线程任务
3.创建一个Runnable接口的实现类对象
4.创建Thread类对象,构造方法中传递Runnable接口的实现类对象
5.调用Thread类中的start方法,开启新的线程执行run方法


方法2相比方法1的好处

1.避免了单继承的局限性
一个类只能继承一个类(一个人只能有一个亲爹),类继承了Thread类就不能继承其他的类。实现了Runnable接口,还可以继承其他的类,实现其他的接口
2.增强了程序的扩展性,降低了程序的耦合性(解耦)
实现Runnpble接口的方式,把设置线程任务和开启新线程进行了分离(解耦)

所以在创建多线程的时候应该尽量使用第二种方法

匿名内部类方式实现多线程

目的:简化代码

线程安全问题

概述:当多个线程同时执行一个线程任务的时候,就会产生冲突,例:通过3个线程输出20至1,在多个线程运行时就会输出重复的数


原理:当某一个线程抢到CPU的执行权并开始执行里面的代码时,就会暂时失去对CPU的控制权,就会导致其他线程抢到CPU并执行里面的代码

解决办法:
1.同步代码块
2.同步方法
3.使用Lock锁

同步代码块

通过创建一个锁对象,与synchronized代码块一同解决该问题,当第一个线程抢到CPU的执行权就会带着锁对象一同执行里面的代码,这时候就算其他线程抢到CPU的执行权,但是没有锁对象,所以就无法执行里面的代码,必须等第一个线程执行完归还锁对象,才能重新争夺锁对象

同步方法

定义一个同步方法,把可能出现安全问题的代码放进去

使用Lock锁

步骤

1.在成员位置创建一一个ReentrantLock对象
2.在可能会出现安全问题的代码前调用Lock接口中的方法Lock获取锁
3.在可能会出现安全问题的代码后调用Lock接口中的方法unLock释放锁

线程池

如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。所以为了解决这一问题引入线程池的概念,即:一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多资源。
线程池的使用步骤:

1.使用线程池的工厂类Executors里边提供的静态方法newFixedThreadPool生产一个指定线程数量的线程池
2.创建一个类,实现Runnable接口,重写run方法,设置线程任务
3.调用ExecutorService中的方法submit,传递线程任务(实现类),开启线程,执行run方法
4.调用ExecutorService中的方法shutdown销毁线程池(不建议执行)


Lambda表达式

目的:简化面向对象的复杂格式
使用前提:

1.使用Lambda必须具有接口,且要求接口中有且仅有一一个抽象方法。
无论是JDK内置的Runnable、Comparator 接口还是自定义的接口,只有当接口中的抽象方法存在且唯一时,才可以使用Lambda。
2.使用Lambda必须具有上下文推断。
也就是方法的参数或局部变量类型必须为Lambda对应的接口类型,才能使用Lambda作为该接口的实例。

格式:(参数列表) -> {一些重写方法的代码};

例:

原文地址:https://www.cnblogs.com/pzbangbangdai/p/12350064.html