线程和进程的概念:
问:简单介绍线程和进程的区别?
答:线程其实就是一条执行路径;
进程就是一个独立的应用程序,在进程中有N多个线程;
进程是线程的集合。
问:为什么使用多线程?
答:多线程的目的是为了提高程序的效率。
问:多线程的使用场景?
答:迅雷下载、数据库连接池、分批发送短信等等。
同步和异步的概念:
同步就是代码从上往下进行执行
异步就是开一条新的执行路径进行执行
多线程创建的方式:
1、继承Thread类
class ThreadDemo1 extends Thread{
@Override
public void run() {
for (int i = 0;i<10;i++){
System.out.println("子线程i:"+i);
}
}
}
public class Test001 {
public static void main(String[] args) {
System.out.println("主线程开始");
ThreadDemo1 threadDemo1 = new ThreadDemo1();
threadDemo1.start();
for (int i = 0;i<50;i++){
System.out.println("主线程i:"+i);
}
System.out.println("主线程结束");
}
}
2、实现Runnable接口
class ThreadDemo2 implements Runnable{
@Override
public void run() {
for (int i = 0;i<10;i++){
System.out.println("子线程i:"+i);
}
}
}
public class Test001 {
public static void main(String[] args) {
System.out.println("主线程开始");
ThreadDemo2 threadDemo2 = new ThreadDemo2();
Thread thread = new Thread(threadDemo2);
thread.start();
for (int i = 0;i<50;i++){
System.out.println("主线程i:"+i);
}
System.out.println("主线程结束");
}
}
3、使用匿名内部类方式
public class Test001 {
public static void main(String[] args) {
System.out.println("主线程开始");
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0;i<10;i++){
System.out.println("子线程i:"+i);
}
}
});
thread.start();
for (int i = 0;i<50;i++){
System.out.println("主线程i:"+i);
}
System.out.println("主线程结束");
}
}
4、使用线程池进行管理创建
多线程的五种状态
守护线程和非守护线程
Java中有两种Thread:
用户线程(非守护线程):非守护线程包括各种普通的线程,java虚拟机在它所有非守护线程离开的时候自动离开。
守护线程:守护线程是用来服务用户线程的,e.g,GC线程就是守护线程。
注:我总结的时候是根据某个培训机构的视频进行总结的,看到这个培训机构对于守护线程的说法有误,在此进行强调说明。
当JVM中有用户线程,那么所有的守护线程都不会停掉,只有当JVM中的用户线程均死亡,那么所有的守护线程将随着JVM一块结束工作(下面紧接着的代码案例可以证明)。守护线程最经典的就是GC线程,也就是说GC线程不是随着主线程的结束而结束的。
package futurePackage;
class ThreadDemo1 extends Thread{
@Override
public void run() {
for (int i = 0;i<20;i++){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("孙线程i:"+i);
}
}
}
class ThreadDemo2 implements Runnable{
@Override
public void run() {
ThreadDemo1 threadDemo1 = new ThreadDemo1(); //在线程2中创建线程1
threadDemo1.setDaemon(true); //设置线程1是线程2的守护线程
threadDemo1.start();
for (int i = 0;i<10;i++){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程i:"+i);
}
}
}
class ThreadDemo3 implements Runnable{
@Override
public void run() {
while (true){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("主线程的守护线程在运行。。。。。。");
}
}
}
public class Test001 {
public static void main(String[] args) throws InterruptedException {
System.out.println("主线程开始");
ThreadDemo2 threadDemo2 = new ThreadDemo2();
ThreadDemo3 threadDemo3 = new ThreadDemo3();
Thread thread1 = new Thread(threadDemo2); //创建线程2
Thread thread2 = new Thread(threadDemo3); //创建线程3
thread1.start();
thread2.setDaemon(true); //设置线程3是主线程的守护线程
thread2.start();
System.out.println("主线程结束");
}
}
守护线程和非守护线程之间的区别:
两者在本质上没有什么区别,唯一的区别之处在于虚拟机的离开,当JVM中所有的线程都是守护线程的时候,JVM就可以退出了;如果还有一个或者以上的非守护线程则不会退出。
守护线程的创建:
thread.setDaemon(true); 这句必须在thread.start()之前执行,否则会报错
Join()方法的使用
Join()方法会让指定线程先行
class ThreadDemo3 implements Runnable{
@Override
public void run() {
for (int i = 0;i<10;i++){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程i:"+i);
}
}
}
public class Test002 {
public static void main(String[] args) throws InterruptedException {
System.out.println("主线程开始");
ThreadDemo3 threadDemo3 = new ThreadDemo3();
Thread thread = new Thread(threadDemo3);
thread.start();
thread.join();
for (int i = 0;i < 10;i++){
Thread.sleep(10);
System.out.println("主线程i:"+i);
}
System.out.println("主线程结束");
}
}