多线程
程序、进程、线程
- 程序是指令和数据的有序集合,本身没有任何运行的含义,是一种静态的概念。
- 进程是执行程序的一次动态过程,是系统资源分配的单位
- 线程:一个进程中可以含有多个线程同时运行,线程是CPU调度和执行的单位
1、多线程实现
1.1 继承Thread类
编写一个类,继承Thread,重写run方法
{public static void main(String[] args){
MyThread myThread = new MyThread();
MyThread myThread2 = new MyThread();
//start方法,启动一个分支线程,启动线程之后,瞬间就结束了
myThread.start();
myThread2.start();
}
}
class MyThread extends Thread{
public void run(){
//运行的程序
}
}
1.2 实现Runnable接口
编写一个类,实现Runnable接口, 但这个类并不是线程
{public static void main(String[] args){
//创建一个可运行的对象
MyRunnable mr = new MyRunnable();
//将可运行的对象封装称线程对象
Thread myThread = new Thread(mr);
myThread.start();
}
}
//这并不是一个线程
class MyRunnable implement Runnable{
public void run(){
//运行的程序
}
}
1.3 线程生命周期
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MzIChO6L-1628395317195)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210314182158000.png)]
1.4 线程操作
获取当前线程对象【写在main方法中,获取的是main方法线程对象;写在子线程中,运行时获取的是子线程对象】
静态方法:currentThread();
Thread t = Thread.currentThread();
设置线程名字
t.setName("xxx");//一个线程默认名字为:Thread-0
获取线程名字
String st = t.getName();
sleep方法:静态方法,参数是毫秒,让当前线程休眠
可以做到间隔特定的时间,执行特定的代码
Thread.sleep(1000);//当前线程休眠【阻塞】1000毫秒
唤醒:interrupt();依靠的是异常的处理机制【使用此方法会让睡眠线程的睡眠方法出异常,进入到catch,结束睡眠】
t.interrupt();//终止t线程的休眠,唤醒t线程
强行终止线程:stop();
t.stop();//已过时,不建议使用
当前线程让出CPU时间片进入就绪状态并重新抢夺CPU时间片:yield();
Thread.yield();
线程插队,强制执行:join();
合理终止
Runnable r = new MyThread();
Thread t = new Thread(r);
t.start();
//合理终止线程:将布尔标记的值变为false;使线程进入else,执行return终止
r.runner = false;
class MyThread extends Runnable{
//打个布尔标记
boolean runner = true;
if(runner){
xxxx;
}else{
//终止线程
return;
}
}
线程优先级(1~10)
//设置线程优先级
setPriority(int xxx);
//得到线程的优先级别
getPriority();
1.5 守护线程
java中线程分为两大类
-
用户线程
-
守护线程
代表性的就是垃圾回收线程(守护线程)
守护线程的特点:
一般守护线程是一个死循环,所有的线程结束,守护线程自动结束
设置守护线程:
Thread t = new MyThread();
//启动线程之前,调用方法设置t线程为守护线程
t.setDaemon(true);
t.start();
1.6 线程安全
什么时候会产生线程安全问题?
- 多线程并发
- 有共享数据
- 共享数据有修改的行为
怎么解决?
线程同步机制,排队执行。
实例方法锁,是对象级别的
静态方法锁,是类级别的
//同步写在具体操作的代码块上
synchronized(需要同步的共享对象){
//需要同步操作的,操作共享数据的代码块
}
//同步写在实例方法体上
//线程运行同一个对象的方法时,会等待排队
public synchronized void useCount(){
}
//同步写在静态方法上
//静态方法不能创建多个,所以只能有一个,是类级别的
//类锁,排他锁,即使创建了一百个对象,锁也只有一把
//线程运行同一个类的不同对象也要等待排队
Lock锁:显式的锁,只有代码块锁,需要开启锁和关闭锁
class{
private static ReentrantLock lock = new ReentrantLock();
public void m(){
lock.lock();//开启锁
try{
//需要同步操作的,操作共享数据的代码块
}
finally{
lock.unlick();//关闭锁
}
}
}
1.7 生产者消费者问题
wait()【等待】和notify()【唤醒】
-不是线程对象的方法,是java中任何一个java对象都有的方法,是Ojbect类的方法
例: 一个银行对象,多个取钱的线程,sleep方法是在线程上让单个线程睡眠,wait方法是使正在银行取钱的线程全部等待,
银行对象调用wait方法和notify方法
Object 0 = new Object();
//让所有在0对象上活动的线程进入等待,无期限等待,直到被唤醒
o.wait();
o.notify();//唤醒一个等待的线程
o.notifyAll();//唤醒全部等待的线程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-56qjDTPg-1628395317204)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210316084843702.png)]
程,sleep方法是在线程上让单个线程睡眠,wait方法是使正在银行取钱的线程全部等待,
银行对象调用wait方法和notify方法
Object 0 = new Object();
//让所有在0对象上活动的线程进入等待,无期限等待,直到被唤醒
o.wait();
o.notify();//唤醒一个等待的线程
o.notifyAll();//唤醒全部等待的线程
[外链图片转存中…(img-56qjDTPg-1628395317204)]