Java多线程基础
目录
一,线程相关概念
1.程序
2.进程
3.线程
4.并发
5.并行
二,线程基本使用
1.创建线程的方法
===继承Thread类===
===实现Runnable接口===
三,继承Thread和实现Runnable的比较
四,线程终止
五,常用方法
==用户线程和守护线程==
六,生命周期
1.线程状态
2.线程状态转换
七,线程同步
1.线程同步机制
2.Synchronized方法
八,互斥锁
1.基本介绍
2.注意事项
九,释放锁
会释放锁的操作
不会释放锁的操作
一,线程相关概念
1.程序
为完成特定任务,用某种语言编写的一组指令的集合(即编写的代码)
2.进程
运行中的程序,进程是程序的一次执行过程,或是正在运行的一个程序,是动态过程,有它自身的产生,存在和消亡过程
3.线程
线程由进程创建,是进程的一个实体,一个进程可以拥有多个线程,根据同一个时刻执行的线程数分为单线程和多线程
4.并发
同一个时刻,多个任务交替执行,造成一种“同时”的错觉(单核CPU实现的多任务就是并发)
5.并行
同一个时刻,多个任务同时执行(多核CPU可以实现并行)
二,线程基本使用
1.创建线程的方法
===继承Thread类===
public class blog {public static void main(String[] args) {m1 M1 = new m1(); M1.start();}
}class m1 extends Thread{//直接继承Thread@Overridepublic void run() {//自己的业务}
}
- 当一个类继承了 Thread 类, 该类就可以当做线程使用
- start0() 是本地方法,是 JVM 调用, 底层是 c/c++实现
- 真正实现多线程的效果, 是 start0(), 而不是run
- run 方法就是一个普通的方法, 没有真正的启动一个线程,就会把 run 方法执行完毕,才向下执行
- 而使用start启动线程时,main 线程启动一个子线程 Thread-0, 主线程不会阻塞, 会继续执行这时 主线程和子线程是交替执行.
===实现Runnable接口===
public class blog {public static void main(String[] args) {m2 m2 = new m2();Thread M2 = new Thread(m2);M2.start();}
}class m2 implements Runnable{//实现RUnnable接口@Overridepublic void run() {//...}
}
Java是单继承的,在某些情况下一个类可能已经继承了某个父类,此时无法继承Thread类,这时可以使用实现Runnable接口的方法创建线程
三,继承Thread和实现Runnable的比较
从Java的设计看,两种方法创建线程本质上没有区别,从jdk帮助文档我们可以看到thread类本身就实现了runnable接口
实现了runnable接口方式更加适合多个线程共享一个资源的情况,并且避免了单继承的限制
四,线程终止
当线程完成任务后,会自动退出
还可以通过使用变量的方法来控制run方法退出的方式停止线程,即通知方式
定义标记变量,默认为true;将loop作为循环条件;提供公共的set方法,用于更新loop
public class blog {public static void main(String[] args) {Thre thre = new Thre();thre.start();int cnt=0;while (cnt<100){try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("Main running"+(++cnt));if(cnt==30){System.out.println("Thre stop");thre.setLoop(false);}}} }class Thre extends Thread{private boolean loop=true;@Overridepublic void run() {while (loop){try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("Thre running");}}public void setLoop(boolean loop) {this.loop = loop;} }
五,常用方法
==用户线程和守护线程==
用户线程:也叫工作线程,当线程的任务执行完或以通知方式结束
守护线程:一般是为工作线程服务的,当所有的用户线程结束,守护线程自动结束(如垃圾回收机制即为守护线程)
守护线程的设置:setDaemon(true);
六,生命周期
1.线程状态
jdk中用Thread.State枚举表示了线程的几种状态
使用getState获取线程状态
2.线程状态转换
七,线程同步
1.线程同步机制
- 在多线程编程,一些敏感数据不允许被多个线程同时访问,此时就使用同步访问技术,保证数据在任何同一时刻,最多有一个线程访问,以保证数据的完整性
- 即当一个线程对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作,其他线程才能对该内存地址进行操作
2.Synchronized方法
1)同步代码块
synchronized (对象){//得到对象的锁,才能操作同步代码//需要被同步的代码
}
2)Synchronized还可以放在方法声明中,表示整个方法为同步方法
public synchronized void m(String name){//需要被同步的代码
}
3)线程同步原理
同步的含义是线程间协作,防止多线程访问共享资源的错误发生。
java实现同步的原理,当一个线程访问临界区时,判断是否有其他线程进入临界区,如果没有它才可以进入临界区,如果已经有线程进入临界区它会被同步挂起,直到进入的线程离开。
八,互斥锁
1.基本介绍
- Java语言中,引入了对象互斥锁的概念,来保证共享数据操作的完整性
- 每个对象都对应一个可称为互斥锁的标记,这个标记用来保证在任意时刻只能有一个线程访问该对象
- 关键字Synchronized来与对象的互斥锁联系,当某个对象用该关键词修饰时,表明该对象在任意时刻只能由一个线程访问
- 同步的局限性:导致程序的执行效率降低
- 同步方法(非静态的)的锁可以是this,也可以是其他对象(要求是同一对象)
- 同步方法(静态的)的锁为当前类本身
2.注意事项
同步方法如果没有使用static修饰:默认锁对象为(this)
如果方法用static修饰,默认锁对象:(当前类.class)
若多个线程都占用了对方的锁资源,但不肯相让,将导致死锁
九,释放锁
会释放锁的操作
1.当前线程的同步方法,同步代码块执行结束
2.当前线程在同步方法,同步代码块中遇到break,return
3.当前线程在同步方法,同步代码块中遇到了未处理的Error或Exception,异常结束
4.当前线程在同步方法,同步代码块中执行了线程对象的wait方法,当前线程暂停并释放锁
不会释放锁的操作
1.线程执行同步方法或代码块时,程序调用sleep,yield方法暂停当前线程的执行
2. 线程执行同步方法或代码块时,其他线程调用了该线程的suspend方法将该线程挂起
注意:应尽量避免使用suspend和resume来控制线程,方法不推荐使用