> 文章列表 > Java多线程基础

Java多线程基础

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.基本介绍

  1. Java语言中,引入了对象互斥锁的概念,来保证共享数据操作的完整性
  2. 每个对象都对应一个可称为互斥锁的标记,这个标记用来保证在任意时刻只能有一个线程访问该对象
  3. 关键字Synchronized来与对象的互斥锁联系,当某个对象用该关键词修饰时,表明该对象在任意时刻只能由一个线程访问
  4. 同步的局限性导致程序的执行效率降低
  5. 同步方法(非静态的)的锁可以是this,也可以是其他对象(要求是同一对象)
  6. 同步方法(静态的)的锁为当前类本身

2.注意事项

同步方法如果没有使用static修饰:默认锁对象为(this)

如果方法用static修饰,默认锁对象:(当前类.class)

若多个线程都占用了对方的锁资源,但不肯相让,将导致死锁 

九,释放锁

会释放锁的操作

1.当前线程的同步方法,同步代码块执行结束

2.当前线程在同步方法,同步代码块中遇到break,return

3.当前线程在同步方法,同步代码块中遇到了未处理的Error或Exception,异常结束

4.当前线程在同步方法,同步代码块中执行了线程对象的wait方法,当前线程暂停并释放锁

不会释放锁的操作

1.线程执行同步方法或代码块时,程序调用sleep,yield方法暂停当前线程的执行

2. 线程执行同步方法或代码块时,其他线程调用了该线程的suspend方法将该线程挂起

注意:应尽量避免使用suspend和resume来控制线程,方法不推荐使用