多线程(一)
一、线程与进程的概念
进程是资源分配的最小单位
线程是程序执行的最小单位(资源调度的最小单位)
1.同一个进程中可以包括多个线程,并且线程共享整个进程的资源(寄存器、堆栈、上下文),一个进程至少包括一个线程。
2.线程没有自己的地址空间,线程包含在进程的地址空间中。一个线程死掉会导致整个进程死掉,而进程之间是独立的,一个进程死掉不会影响其他进程。进程中的线程共享进程的内存和资源,他们共享代码段、数据段、堆,但是线程间拥有自己的栈。
3.线程是轻量级的进程,它的创建和销毁所需要的时间比进程小很多。
4.进程间相互独立,通信困难,常用的IPC:管道,信号,套接字,共享内存,消息队列等;线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。
二、为什么要使用多线程——》多线程的优势
1.使用多线程有可能提升效率
某些场景下,如果任务的数量不够,启动线程占用的时间反倒成为耗时较多的,导致多线程不一定快
2. 某些场景下,主线程会阻塞,导致必须使用多线程工作:(IO相关)——模型更简单 NIO/协程
3. 某些场景下,主线程不允许做大量的计算,导致大量的计算必须使用多线程(GUI图形界面的开发)
三、如何创建多线程对象 -Thread对象
1.继承Thread类 + 覆写run方法 (Thread是个线程)
2.实现Runnable接口+覆写run 方法 (Runnable是个任务)
把Runnable对象作为Thread类的构造方法的参数
3.Thread类也实现了Runnable接口
- Thread类与MyThread(实现了Runnable接口)是一个典型的代理设计模式
Thread类负责辅助真实业务操作(资源调度,创建多线程并启动),MyThread负责真实业务的实现(run方法具体要干什么事) - 使用Runnable接口实现的多线程程序类可以更好的体现共享
以上三种方法实现代码示例
public class CreateThread {
private static long n = 1_0000_0000L;
//
private static class MyThread extends Thread{
@Override
public void run() {
long r = 0;
for(long i = 0;i < n;i++){
r += (i*i);
}
System.out.println(r);
}
}
private static class MyRunnable implements Runnable{
@Override
public void run() {
long r = 0;
for(long i = 0;i < n;i++){
r += (i*i);
}
System.out.println(r);
}
}
public static void main(String[] args) {
//第一种方法
MyThread myThread = new MyThread();
myThread.start();
//第二种方法
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();
//第三种方法
MyThread myThread2 = new MyThread();
Thread thread1 = new Thread(myThread2);
thread1.start();
}
}
适用场景:
通过1启动的线程对象,myThread好处是在run方法中可以直接使用this代表当前的线程对象,但是缺点是:类的继承是单继承
JVM停止的条件:所有非精灵线程都退出,才会退出,并不是主线程退出就退出