线程:程序执行的最小单位
进程:程序运行的基本单位(包含至少一个线程)
比如:QQ是一个进程
它包含多个线程:
-
聊天消息接收线程
-
文件传输线程
-
界面刷新线程
-
网络状态检测线程

++并发:在同一时刻,有多个指令在单个CPU上交替执行
并行:在同一时刻,有多个指令在多个CPU上同时执行++
三种实现方式
++继承Thread类的方式进行实现
实现Runnable接口的方式进行实现
利用Callable接口和Future接口方式实现++
1.继承Thread类(Thread自己就表示一个线程)
逻辑:自己定义一个类并继承Thread方法,重写run方法,创建子类的对象,并启动线程


模糊的地方:关于get set方法的使用
为什么可以在 main 方法中直接调用 setName?
-
setName() 是 Thread 类的 public 方法
-
MyThread 继承了 Thread 类
-
在同一个包(package a03)中,可以访问 public 和 protected 方法
-
main 方法在 MyThread 类的内部,可以访问所有成员方法
2.实现Runnable接口
逻辑:创建一个类实现Runnable接口,并重写run方法,在测试类中创建自己类的对象(表示多线程要执行的任务),再创建Thread类对象,把自己类的对象传入里面(任务),并开启线程。
实现接口时,我们不能直接调用getName这个方法,因为这个方法是在Thread这个类中的,但我们可以获取到当前多线程的对象,让对象去调用这个方法。


3.利用Callable和Future接口实现
逻辑:创建一个类实现Callable接口并重写call(是有返回值的,表示多线程运行的结果),在测试类中,先创建这个类的对象(表示多线程要执行的任务),再创建Future实现类的对象(管理多线程运行的结果)(Future本身是一个接口),在创建Thread对象

++这里的泛型表示返回值的类型,比如我要求1-100的和,返回值就是整数。++

三种实现方法对比

Thread的常用成员方法
常见的成员方法
方法名称
String getName() 返回此线程的名称
void setName(String name) 设置线程的名字(构造方法也可以设置名字)
static Thread currentThread() 获取当前线程的对象
static void sleep(long time) 让线程休眠指定的时间,单位为毫秒
setPriority(int newPriority) 设置线程的优先级
final int getPriority() 获取线程的优先级
final void setDaemon(boolean on) 设置为守护线程
public static void yield() 出让线程/礼让线程
public static void join() 插入线程/插队线程
注意:子类不能继承父类的构造方法,如果要使用,就要用super关键字调用方法,Ctrl+alt+M
静态方法通过类名直接调用

线程的优先级:
越大优先级越高,1-10,默认是5,只能说是概率,不是一定

守护线程

出让线程

插入线程

线程的生命周期

线程安全
++线程执行时具有随机性,CPU的执行权随时都有可能被其他线程抢走++
++static修饰变量,表示这个类所有的对象都共享这个数据++
同步代码块

++锁对象一定要是唯一的,一般是当前类的字节码文件++

++锁要写在循环的里面,否则一个就执行完了++
同步方法

逻辑:先写同步代码块,再把同步代码块抽取成同步方法