1、三高:高可用、高性能、高并发、
2、多线程:同一时间执行多个任务
3、程序、进程、线程:
(1)程序:静态的代码
(2)进程:CPU调度的代码(动态概念)
(3)线程:一个进程中开辟多条路径
4、进程和线程的区别:
(1)根本区别:进程:作为资源分配的单位;线程:CPU调度和执行的单位
(2)开销:进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销;线程:可以看做是轻量级进程,同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换的开销小。
(3)所处环境:进程:在操作系统中可以同时运行多个任务;线程:在同一应用程序中有多个顺序流同时执行。
(4)分配内存:进程:系统运行时会给每一个进程分配不同的内存区域;线程:除了CPU之外,不会为线程分配内存,(线程所使用的资源是它所属的进程的资源),线程只能共享资源。
(5)包含关系:线程是进程的一部分,一个进程如果只有一条线程,那么该进程被称为单线程进程,否则叫多线程进程。
5、核心概念:
》线程才是独立执行的路径;
》程序运行时即使没有自己创建多线程,后台也会存在多线程。例如gc(垃圾回收)线程;
》一个线程中的多个进程,由调度器统一安排调度,调度器是与操作系统紧密相关的,先后顺序无法认为干预;
》操作同一份资源(共享资源)时,会存在资源抢夺,需要加入并发控制;
》每个线程有自己的工作空间,通过工作空间与主内存交互,线程如果操作不当会造成数据不一致
1、创建线程
(1)继承Thread类,重写run方法,创建子类对象并调用子类start()方法;
run方法内是线程需要执行的动作,start方法的作用是将线程创建好丢给CPU,等待CPU的调度。切记:start方法只是告知CPU当前线程已进入就绪态,不会立即执行该线程
如果直接调用子类的run方法,效果就是普通方法的调用,必须顺序执行,不会出现多线程。
(2)实现Runnable接口,重写run方法,创建实现类对象并丢给Thread类,调用Thread类的Start方法;推荐使用该方法,避免单继承的局限性。
因为Runnable接口没有start方法,不能丢给CPU,所以需要new Thread(new PrimeRun(11)).start();
run方法不允许抛出异常。没有返回值
(3)实现Callable接口,重写call方法(juc);
call方法允许抛出异常。有返回值
使用方法:
1.创建目标对象:(即实现Callable接口的对象)
2.创建执行服务:ExecutorService ser = Executors.newFixedThreadPool(1);
3.提交执行:Future
4.获取结果:boolean r1 = result.get();
5.关闭服务:ser.shutdownNow();
1、真实角色和代理角色实现同一个代理接口
2、代理接口定义代理方法
3、真实角色实现代理方法
4、代理角色声明代理接口,在实现代理方法中调用真实角色重写的方法(多态)
使用要求:
1、目的是简化匿名内部类的使用,避免匿名内部类过多,实质是函数式编程;
2、要求传入的参数是一个接口,并且该接口内部只有一个抽象方法;
3、注意:一定要指定接口名,要不然系统不知道到底推导哪个;
例:
注意:运行状态被阻塞结束后不能马上进入运行态;线程死亡后不能复活(不能继续执行)
线程有自己的工作空间,从主内存拷贝数据到工作空间然后执行
到达就绪态的四种方式:调用start()方法(线程刚刚调用);阻塞状态解除;调用yield方法;jvm主动切换到其他线程
到达阻塞态的四种方式:sleep;wait;join;调用其他资源(IO操作)
1、停止线程
一般停止线程主要有两种方式:线程自动执行完毕或认为停止线程调用
不建议使用stop()方法和distory()方法
可以在run方法里面加一个标识去人为控制线程执行
例:
package com.zzu.threadmethod;
public class Terminal implements Runnable{
boolean flag = true;
@Override
public void run() {
for(int i=0;i<100;i++) {
if(!flag) {
break;
}
System.out.println("线程第"+i+"次执行");
}
}
public void terminal() {
flag = false;
}
public static void main(String[] args) {
Terminal terminal = new Terminal();
new Thread(terminal).start();
for(int i=0;i<100;i++){
if(i==50) {
terminal.terminal();
System.out.println("线程结束");
}
System.out.println("main第"+i+"次运行");
}
}
}
2、sleep方法
sleep(时间)指定当前线程阻塞的毫秒数
sleep存在异常InterruptedException
sleep时间到达后线程进入就绪态
sleep可以模拟网络延时、倒计时等
sleep每个对象都有一个锁,sleep不会释放锁(不会释放资源,针对wait来说)
用法:Thread.sleep(1000);哪个线程体执行该方法,该线程体阻塞
一般用来模拟网络延时或者倒计时
3、yield
礼让线程,让当前执行线程从执行态进入就绪态,让CPU重新调度
调用方法:Thread.yield();
主要作用:避免一个线程占用CPU时间过久
4、join
join合并线程,待此线程执行完成,再执行其他线程,其他线程阻塞
相当于插队
使用方法: 在被插队的线程中新建插队的线程对象。并执行
package com.zzu.threadmethod;
public class Join {
public static void main(String[] args) {
new Thread(new FThread()).start();//创建父线程
}
}
class FThread implements Runnable{
@Override
public void run() {
SThread s = new SThread();
Thread a = new Thread(s);
a.start();//子线程创建
try {
for (int i = 0; i <10; i++) {
System.out.println("fatherThread第"+i+"次执行");
if(i==3) {
a.join();//插队
}
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class SThread implements Runnable{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("------->sonThread第"+i+"次执行");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Thread.State:
NEW:尚未启动的线程
RUNNABLE:在Java虚拟机中执行的线程
BLOCKED:被阻塞等待监视器锁定的线程
WAITING:在等待另一个线程执行特定动作的线程
TIMED_WAITING:等待另一个线程执行动作达到指定时间的线程
TERMINATED:已退出的线程
package com.zzu.threadmethod;
public class AllState implements Runnable{
@Override
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Thread t = new Thread(new AllState());
System.out.println(t.getState());
t.start();
for(;t.getState()!=Thread.State.TERMINATED;) {
System.out.println(t.getState());
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(t.getState());
}
}
1、priority优先级范围1-10,优先级越高被调用的可能性越大(但不是绝对);
2、priority的三个基本常量:MIN_PRIORITY=1;MAX_PRIORITY=10;NORM_PRIORITY=5;
3、获取当前线程的优先级:Thread.currentThread().getPriority();
4、设置线程优先级:t.setPriority(1-10);注意,设置优先级必须在线程启动前
1、线程分为用户线程和守护线程(Daemon)
2、虚拟机必须确保用户线程执行完毕
3、虚拟机不用等待守护线程执行完毕
4、守护线程:后台记录操作日志、监控内存使用等
package com.zzu.threadmethod;
public class DeamonTest implements Runnable{
public static void main(String[] args) {
Thread a = new Thread(new DeamonTest());
Thread b = new Thread(new DeamonThread());
b.setDaemon(true);
a.start();
b.start();
}
@Override
public void run() {
for(int i=0;i<5;i++) {
System.out.println("用户线程---------");
}
}
}
class DeamonThread implements Runnable{
@Override
public void run() {
while(true) {
System.out.println("守护线程---------");
}
}
}
1、currentThread()//当前线程
2、setName()、getName()//设置代理姓名
3、isAlive()//线程是否还活着