并发编程基础

线程和进程的概念:

 问:简单介绍线程和进程的区别?

答:线程其实就是一条执行路径;

进程就是一个独立的应用程序,在进程中有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("主线程结束");
    }
}