多线程
进程和线程的概念
进程:正在进行中的程序。
线程:进程中一个负责程序执行的控制单元(执行路径),一个进程中可以多执行路径,称之为多线程。
创建线程的两种方式
继承Thread类
创建线程方式一:继承Thread类。
步骤:
1,定义一个类继承Thread类。
2,覆盖Thread类中的run方法。
3,直接创建Thread的子类对象创建线程。
4,调用start方法开启线程并调用线程的任务run方法执行。
class MyThread extends Thread{
public void run(){
System.out.println("多线程开启");//需要多线程的执行的内容
}
}
public class ThreadTest {
public static void main(String[] args) {
Thread myThread1 = new MyThread();//创建线程并覆盖run()方法
Thread myThread2 = new MyThread();
myThread1.start();
myThread2.start();
}
}
实现Runnable接口
创建线程方式二:实现Runnable接口。
步骤:
1,定义类实现Runnable接口。
2,覆盖接口中的run方法,将线程的任务代码封装到run方法中。
3,通过Thread类创建线程对象,并将实现Runnable接口的子类对象作为Thread类的构造函数的参数进行传递。
4,调用线程对象的start方法开启线程。
class MyRunThread implements Runnable{
public void run() {
System.out.println("多线程开启");//需要多线程的执行的内容
}
}
public class ThreadTest {
public static void main(String[] args) {
MyRunThread runThread = new MyRunThread();
Thread myThread1 = new Thread(runThread);//创造线程并把MyRunThread类对象作构造函数的参数
Thread myThread2 = new Thread(runThread);
myThread1.start();
myThread2.start();
}
}
线程的生命周期(状态)
线程的调度
Java虚拟机会按照特定的机制为程序中的每个线程分配CPU的使用权,这种机制被称作线程的调度。
线程的优先级
线程的优先级用1~10之间的整数来表示,数字越大优先级越高。可以通过Thread类的setPriority(int newPriority)方法对其进行设置。
线程休眠(sleep(long millis))
线程休眠也就是让当前线程进入阻塞状态将UPU让给其他线程,通过Thread类的静态方法sleep(long millis)实现,注意此方法会声明抛出InterruptedException异常。(可实现线程的交替执行)
线程让步(yield())
线程让步也是让正在运行的线程暂停,但和线程休眠不同的是它是让线程进入就绪状态而非阻塞状态,通过Thread类的静态方法yield()实现。
线程插队(join())
当某个线程调用join()方法时,当前线程将被“插队”,需等待调用join()方法的线程执行完毕之后再继续运行。join() 方法有带参数和无参数。
线程唤醒
多线程同步(安全问题|synchronized)
当多个线程去访问同一个资源时,可能会引发一些安全问题。
解决办法:同步。让某个资源在一个时刻只能被一个线程访问。(加锁)
同步代码块
格式:
synchronized(锁对象lock) {
需要同步操作共享资源的内容;
}
同步方法
格式:
synchronized 返回值类型 方法名 ([参数1,···]){}
同步方法和同步代码块的区别:
- 同步方法的锁是固定的this。
- 同步代码块的锁是任意的对象。
- 建议使用同步代码块。
死锁
线程在执行同步代码时,不仅每次都要判断锁的状态,消耗资源效率低,而且还可以存在两个线程都在等待对方的锁,造成程序的停滞,这种现象称为死锁。(核心理解:相互等待)
class DeadLockThread implements Runnable{
static Object lock1 = new Object();//lock1锁对象
static Object lock2 = new Object();//lock2锁对象
boolean flag;
public void run() {
if(flag==true){
while(true){
synchronized(lock1){//lock1锁对象上的同步代码块
System.out.println(Thread.currentThread().getName());
synchronized(lock2){//lock2锁对象上的同步代码块
System.out.println("此地不到达");
}
}
}
}else{
while(true){
synchronized(lock2){
System.out.println(Thread.currentThread().getName());
synchronized(lock1){
System.out.println("此地不到达");
}
}
}
}
}
}
public class DeadLock {
public static void main(String[] args) {
DeadLockThread d1 = new DeadLockThread();
DeadLockThread d2 = new DeadLockThread();
d1.flag = true;
d2.flag = false;
new Thread(d1,"d1").start();//创建并开启线程d1
new Thread(d2,"d2").start();//创建并开启线程d2
}
}
输出:
d1
d2原因:d1线程在拿到lock1后需得到lock2,但此时lock2在d2线程上,而d2线程又需要lock1,lock1又在d1上,所有形成了死锁。